Merge "Pass $key into CommentStore methods and use MediawikiServices"

This commit is contained in:
jenkins-bot 2018-02-06 15:31:59 +00:00 committed by Gerrit Code Review
commit bbedc24556
50 changed files with 533 additions and 300 deletions

View file

@ -216,6 +216,15 @@ changes to languages because of Phabricator reports.
* The no-op method Skin::showIPinHeader(), deprecated in 1.27, was removed.
* \ObjectFactory (no namespace) is deprecated, the namespaced \Wikimedia\ObjectFactory
from the wikimedia/object-factory library should be used instead.
* CommentStore::newKey is deprecated. Get an instance from MediaWikiServices instead.
* The following CommentStore methods have had their signatures changed to introduce a $key parameter,
usage of the methods on instances retrieved from CommentStore::newKey will remain unchanged but deprecated:
* CommentStore::getFields
* CommentStore::getJoin
* CommentStore::getComment
* CommentStore::getCommentLegacy
* CommentStore::insert
* CommentStore::insertWithTemplate
== Compatibility ==
MediaWiki 1.31 requires PHP 5.5.9 or later. Although HHVM 3.18.5 or later is supported,

View file

@ -222,7 +222,7 @@ class Block {
'ipb_block_email',
'ipb_allow_usertalk',
'ipb_parent_block_id',
] + CommentStore::newKey( 'ipb_reason' )->getFields();
] + CommentStore::getStore()->getFields( 'ipb_reason' );
}
/**
@ -235,7 +235,7 @@ class Block {
* - joins: (array) to include in the `$join_conds` to `IDatabase->select()`
*/
public static function getQueryInfo() {
$commentQuery = CommentStore::newKey( 'ipb_reason' )->getJoin();
$commentQuery = CommentStore::getStore()->getJoin( 'ipb_reason' );
return [
'tables' => [ 'ipblocks' ] + $commentQuery['tables'],
'fields' => [
@ -460,9 +460,9 @@ class Block {
// I wish I didn't have to do this
$db = wfGetDB( DB_REPLICA );
$this->mExpiry = $db->decodeExpiry( $row->ipb_expiry );
$this->mReason = CommentStore::newKey( 'ipb_reason' )
$this->mReason = CommentStore::getStore()
// Legacy because $row may have come from self::selectFields()
->getCommentLegacy( $db, $row )->text;
->getCommentLegacy( $db, 'ipb_reason', $row )->text;
$this->isHardblock( !$row->ipb_anon_only );
$this->isAutoblocking( $row->ipb_enable_autoblock );
@ -654,7 +654,7 @@ class Block {
'ipb_block_email' => $this->prevents( 'sendemail' ),
'ipb_allow_usertalk' => !$this->prevents( 'editownusertalk' ),
'ipb_parent_block_id' => $this->mParentBlockId
] + CommentStore::newKey( 'ipb_reason' )->insert( $dbw, $this->mReason );
] + CommentStore::getStore()->insert( $dbw, 'ipb_reason', $this->mReason );
return $a;
}
@ -670,7 +670,7 @@ class Block {
'ipb_create_account' => $this->prevents( 'createaccount' ),
'ipb_deleted' => (int)$this->mHideName, // typecast required for SQLite
'ipb_allow_usertalk' => !$this->prevents( 'editownusertalk' ),
] + CommentStore::newKey( 'ipb_reason' )->insert( $dbw, $this->mReason );
] + CommentStore::getStore()->insert( $dbw, 'ipb_reason', $this->mReason );
}
/**

View file

@ -20,6 +20,7 @@
* @file
*/
use MediaWiki\MediaWikiServices;
use Wikimedia\Rdbms\IDatabase;
/**
@ -79,40 +80,71 @@ class CommentStore {
*/
protected static $formerTempTables = [];
/** @var string */
protected $key;
/**
* @since 1.30
* @deprecated in 1.31
* @var string|null
*/
protected $key = null;
/** @var int One of the MIGRATION_* constants */
protected $stage;
/** @var array|null Cache for `self::getJoin()` */
protected $joinCache = null;
/** @var array[] Cache for `self::getJoin()` */
protected $joinCache = [];
/** @var Language Language to use for comment truncation */
protected $lang;
/**
* @param string $key A key such as "rev_comment" identifying the comment
* field being fetched.
* @param Language $lang Language to use for comment truncation. Defaults
* to $wgContLang.
* @param int $migrationStage One of the MIGRATION_* constants
*/
public function __construct( $key, Language $lang = null ) {
global $wgCommentTableSchemaMigrationStage, $wgContLang;
$this->key = $key;
$this->stage = $wgCommentTableSchemaMigrationStage;
$this->lang = $lang ?: $wgContLang;
public function __construct( Language $lang, $migrationStage ) {
$this->stage = $migrationStage;
$this->lang = $lang;
}
/**
* Static constructor for easier chaining
* @deprecated in 1.31 Should not be constructed with a $key, use CommentStore::getStore
* @param string $key A key such as "rev_comment" identifying the comment
* field being fetched.
* @return CommentStore
*/
public static function newKey( $key ) {
return new CommentStore( $key );
global $wgCommentTableSchemaMigrationStage, $wgContLang;
// TODO uncomment once not used in extensions
// wfDeprecated( __METHOD__, '1.31' );
$store = new CommentStore( $wgContLang, $wgCommentTableSchemaMigrationStage );
$store->key = $key;
return $store;
}
/**
* @since 1.31
* @deprecated in 1.31 Use DI to inject a CommentStore instance into your class.
* @return CommentStore
*/
public static function getStore() {
return MediaWikiServices::getInstance()->getCommentStore();
}
/**
* Compat method allowing use of self::newKey until removed.
* @param string|null $methodKey
* @throw InvalidArgumentException
* @return string
*/
private function getKey( $methodKey = null ) {
$key = $this->key !== null ? $this->key : $methodKey;
if ( $key === null ) {
// @codeCoverageIgnoreStart
throw new InvalidArgumentException( '$key should not be null' );
// @codeCoverageIgnoreEnd
}
return $key;
}
/**
@ -123,23 +155,29 @@ class CommentStore {
*
* @note Use of this method may require a subsequent database query to
* actually fetch the comment. If possible, use `self::getJoin()` instead.
*
* @since 1.30
* @since 1.31 Method signature changed, $key parameter added (with deprecated back compat)
* @param string $key A key such as "rev_comment" identifying the comment
* field being fetched.
* @return string[] to include in the `$vars` to `IDatabase->select()`. All
* fields are aliased, so `+` is safe to use.
*/
public function getFields() {
public function getFields( $key = null ) {
$key = $this->getKey( $key );
$fields = [];
if ( $this->stage === MIGRATION_OLD ) {
$fields["{$this->key}_text"] = $this->key;
$fields["{$this->key}_data"] = 'NULL';
$fields["{$this->key}_cid"] = 'NULL';
$fields["{$key}_text"] = $key;
$fields["{$key}_data"] = 'NULL';
$fields["{$key}_cid"] = 'NULL';
} else {
if ( $this->stage < MIGRATION_NEW ) {
$fields["{$this->key}_old"] = $this->key;
$fields["{$key}_old"] = $key;
}
if ( isset( self::$tempTables[$this->key] ) ) {
$fields["{$this->key}_pk"] = self::$tempTables[$this->key]['joinPK'];
if ( isset( self::$tempTables[$key] ) ) {
$fields["{$key}_pk"] = self::$tempTables[$key]['joinPK'];
} else {
$fields["{$this->key}_id"] = "{$this->key}_id";
$fields["{$key}_id"] = "{$key}_id";
}
}
return $fields;
@ -151,56 +189,61 @@ class CommentStore {
* Each resulting row should be passed to `self::getComment()` to get the
* actual comment.
*
* @since 1.30
* @since 1.31 Method signature changed, $key parameter added (with deprecated back compat)
* @param string $key A key such as "rev_comment" identifying the comment
* field being fetched.
* @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()`
* All tables, fields, and joins are aliased, so `+` is safe to use.
*/
public function getJoin() {
if ( $this->joinCache === null ) {
public function getJoin( $key = null ) {
$key = $this->getKey( $key );
if ( !array_key_exists( $key, $this->joinCache ) ) {
$tables = [];
$fields = [];
$joins = [];
if ( $this->stage === MIGRATION_OLD ) {
$fields["{$this->key}_text"] = $this->key;
$fields["{$this->key}_data"] = 'NULL';
$fields["{$this->key}_cid"] = 'NULL';
$fields["{$key}_text"] = $key;
$fields["{$key}_data"] = 'NULL';
$fields["{$key}_cid"] = 'NULL';
} else {
$join = $this->stage === MIGRATION_NEW ? 'JOIN' : 'LEFT JOIN';
if ( isset( self::$tempTables[$this->key] ) ) {
$t = self::$tempTables[$this->key];
$alias = "temp_$this->key";
if ( isset( self::$tempTables[$key] ) ) {
$t = self::$tempTables[$key];
$alias = "temp_$key";
$tables[$alias] = $t['table'];
$joins[$alias] = [ $join, "{$alias}.{$t['pk']} = {$t['joinPK']}" ];
$joinField = "{$alias}.{$t['field']}";
} else {
$joinField = "{$this->key}_id";
$joinField = "{$key}_id";
}
$alias = "comment_$this->key";
$alias = "comment_$key";
$tables[$alias] = 'comment';
$joins[$alias] = [ $join, "{$alias}.comment_id = {$joinField}" ];
if ( $this->stage === MIGRATION_NEW ) {
$fields["{$this->key}_text"] = "{$alias}.comment_text";
$fields["{$key}_text"] = "{$alias}.comment_text";
} else {
$fields["{$this->key}_text"] = "COALESCE( {$alias}.comment_text, $this->key )";
$fields["{$key}_text"] = "COALESCE( {$alias}.comment_text, $key )";
}
$fields["{$this->key}_data"] = "{$alias}.comment_data";
$fields["{$this->key}_cid"] = "{$alias}.comment_id";
$fields["{$key}_data"] = "{$alias}.comment_data";
$fields["{$key}_cid"] = "{$alias}.comment_id";
}
$this->joinCache = [
$this->joinCache[$key] = [
'tables' => $tables,
'fields' => $fields,
'joins' => $joins,
];
}
return $this->joinCache;
return $this->joinCache[$key];
}
/**
@ -209,12 +252,13 @@ class CommentStore {
* Shared implementation for getComment() and getCommentLegacy()
*
* @param IDatabase|null $db Database handle for getCommentLegacy(), or null for getComment()
* @param string $key A key such as "rev_comment" identifying the comment
* field being fetched.
* @param object|array $row
* @param bool $fallback
* @return CommentStoreComment
*/
private function getCommentInternal( IDatabase $db = null, $row, $fallback = false ) {
$key = $this->key;
private function getCommentInternal( IDatabase $db = null, $key, $row, $fallback = false ) {
$row = (array)$row;
if ( array_key_exists( "{$key}_text", $row ) && array_key_exists( "{$key}_data", $row ) ) {
$cid = isset( $row["{$key}_cid"] ) ? $row["{$key}_cid"] : null;
@ -333,12 +377,27 @@ class CommentStore {
* If you need to fake a comment in a row for some reason, set fields
* `{$key}_text` (string) and `{$key}_data` (JSON string or null).
*
* @since 1.30
* @since 1.31 Method signature changed, $key parameter added (with deprecated back compat)
* @param string $key A key such as "rev_comment" identifying the comment
* field being fetched.
* @param object|array $row Result row.
* @param bool $fallback If true, fall back as well as possible instead of throwing an exception.
* @return CommentStoreComment
*/
public function getComment( $row, $fallback = false ) {
return $this->getCommentInternal( null, $row, $fallback );
public function getComment( $key, $row = null, $fallback = false ) {
// Compat for method sig change in 1.31 (introduction of $key)
if ( $this->key !== null ) {
$fallback = $row;
$row = $key;
$key = $this->getKey();
}
if ( $row === null ) {
// @codeCoverageIgnoreStart
throw new InvalidArgumentException( '$row must not be null' );
// @codeCoverageIgnoreEnd
}
return $this->getCommentInternal( null, $key, $row, $fallback );
}
/**
@ -351,13 +410,28 @@ class CommentStore {
* If you need to fake a comment in a row for some reason, set fields
* `{$key}_text` (string) and `{$key}_data` (JSON string or null).
*
* @since 1.30
* @since 1.31 Method signature changed, $key parameter added (with deprecated back compat)
* @param IDatabase $db Database handle to use for lookup
* @param string $key A key such as "rev_comment" identifying the comment
* field being fetched.
* @param object|array $row Result row.
* @param bool $fallback If true, fall back as well as possible instead of throwing an exception.
* @return CommentStoreComment
*/
public function getCommentLegacy( IDatabase $db, $row, $fallback = false ) {
return $this->getCommentInternal( $db, $row, $fallback );
public function getCommentLegacy( IDatabase $db, $key, $row = null, $fallback = false ) {
// Compat for method sig change in 1.31 (introduction of $key)
if ( $this->key !== null ) {
$fallback = $row;
$row = $key;
$key = $this->getKey();
}
if ( $row === null ) {
// @codeCoverageIgnoreStart
throw new InvalidArgumentException( '$row must not be null' );
// @codeCoverageIgnoreEnd
}
return $this->getCommentInternal( $db, $key, $row, $fallback );
}
/**
@ -443,23 +517,25 @@ class CommentStore {
/**
* Implementation for `self::insert()` and `self::insertWithTempTable()`
* @param IDatabase $dbw
* @param string $key A key such as "rev_comment" identifying the comment
* field being fetched.
* @param string|Message|CommentStoreComment $comment
* @param array|null $data
* @return array [ array $fields, callable $callback ]
*/
private function insertInternal( IDatabase $dbw, $comment, $data ) {
private function insertInternal( IDatabase $dbw, $key, $comment, $data ) {
$fields = [];
$callback = null;
$comment = $this->createComment( $dbw, $comment, $data );
if ( $this->stage <= MIGRATION_WRITE_BOTH ) {
$fields[$this->key] = $this->lang->truncate( $comment->text, 255 );
$fields[$key] = $this->lang->truncate( $comment->text, 255 );
}
if ( $this->stage >= MIGRATION_WRITE_BOTH ) {
if ( isset( self::$tempTables[$this->key] ) ) {
$t = self::$tempTables[$this->key];
if ( isset( self::$tempTables[$key] ) ) {
$t = self::$tempTables[$key];
$func = __METHOD__;
$commentId = $comment->id;
$callback = function ( $id ) use ( $dbw, $commentId, $t, $func ) {
@ -473,7 +549,7 @@ class CommentStore {
);
};
} else {
$fields["{$this->key}_id"] = $comment->id;
$fields["{$key}_id"] = $comment->id;
}
}
@ -485,17 +561,34 @@ class CommentStore {
*
* @note It's recommended to include both the call to this method and the
* row insert in the same transaction.
*
* @since 1.30
* @since 1.31 Method signature changed, $key parameter added (with deprecated back compat)
* @param IDatabase $dbw Database handle to insert on
* @param string $key A key such as "rev_comment" identifying the comment
* field being fetched.
* @param string|Message|CommentStoreComment $comment As for `self::createComment()`
* @param array|null $data As for `self::createComment()`
* @return array Fields for the insert or update
*/
public function insert( IDatabase $dbw, $comment, $data = null ) {
if ( isset( self::$tempTables[$this->key] ) ) {
throw new InvalidArgumentException( "Must use insertWithTempTable() for $this->key" );
public function insert( IDatabase $dbw, $key, $comment = null, $data = null ) {
// Compat for method sig change in 1.31 (introduction of $key)
if ( $this->key !== null ) {
$data = $comment;
$comment = $key;
$key = $this->key;
}
if ( $comment === null ) {
// @codeCoverageIgnoreStart
throw new InvalidArgumentException( '$comment can not be null' );
// @codeCoverageIgnoreEnd
}
list( $fields ) = $this->insertInternal( $dbw, $comment, $data );
if ( isset( self::$tempTables[$key] ) ) {
throw new InvalidArgumentException( "Must use insertWithTempTable() for $key" );
}
list( $fields ) = $this->insertInternal( $dbw, $key, $comment, $data );
return $fields;
}
@ -507,7 +600,12 @@ class CommentStore {
*
* @note It's recommended to include both the call to this method and the
* row insert in the same transaction.
*
* @since 1.30
* @since 1.31 Method signature changed, $key parameter added (with deprecated back compat)
* @param IDatabase $dbw Database handle to insert on
* @param string $key A key such as "rev_comment" identifying the comment
* field being fetched.
* @param string|Message|CommentStoreComment $comment As for `self::createComment()`
* @param array|null $data As for `self::createComment()`
* @return array Two values:
@ -515,14 +613,26 @@ class CommentStore {
* - callable Function to call when the primary key of the row being
* inserted/updated is known. Pass it that primary key.
*/
public function insertWithTempTable( IDatabase $dbw, $comment, $data = null ) {
if ( isset( self::$formerTempTables[$this->key] ) ) {
wfDeprecated( __METHOD__ . " for $this->key", self::$formerTempTables[$this->key] );
} elseif ( !isset( self::$tempTables[$this->key] ) ) {
throw new InvalidArgumentException( "Must use insert() for $this->key" );
public function insertWithTempTable( IDatabase $dbw, $key, $comment = null, $data = null ) {
// Compat for method sig change in 1.31 (introduction of $key)
if ( $this->key !== null ) {
$data = $comment;
$comment = $key;
$key = $this->getKey();
}
if ( $comment === null ) {
// @codeCoverageIgnoreStart
throw new InvalidArgumentException( '$comment can not be null' );
// @codeCoverageIgnoreEnd
}
list( $fields, $callback ) = $this->insertInternal( $dbw, $comment, $data );
if ( isset( self::$formerTempTables[$key] ) ) {
wfDeprecated( __METHOD__ . " for $key", self::$formerTempTables[$key] );
} elseif ( !isset( self::$tempTables[$key] ) ) {
throw new InvalidArgumentException( "Must use insert() for $key" );
}
list( $fields, $callback ) = $this->insertInternal( $dbw, $key, $comment, $data );
if ( !$callback ) {
$callback = function () {
// Do nothing.

View file

@ -2798,7 +2798,8 @@ ERROR;
if ( $this->wasDeletedSinceLastEdit() && 'save' == $this->formtype ) {
$username = $this->lastDelete->user_name;
$comment = CommentStore::newKey( 'log_comment' )->getComment( $this->lastDelete )->text;
$comment = CommentStore::getStore()
->getComment( 'log_comment', $this->lastDelete )->text;
// It is better to not parse the comment at all than to have templates expanded in the middle
// TODO: can the checkLabel be moved outside of the div so that wrapWikiMsg could be used?
@ -3810,7 +3811,7 @@ ERROR;
*/
protected function getLastDelete() {
$dbr = wfGetDB( DB_REPLICA );
$commentQuery = CommentStore::newKey( 'log_comment' )->getJoin();
$commentQuery = CommentStore::getStore()->getJoin( 'log_comment' );
$data = $dbr->selectRow(
[ 'logging', 'user' ] + $commentQuery['tables'],
[

View file

@ -89,7 +89,7 @@ class FeedUtils {
$timestamp,
$row->rc_deleted & Revision::DELETED_COMMENT
? wfMessage( 'rev-deleted-comment' )->escaped()
: CommentStore::newKey( 'rc_comment' )->getComment( $row )->text,
: CommentStore::getStore()->getComment( 'rc_comment', $row )->text,
$actiontext
);
}

View file

@ -1,6 +1,7 @@
<?php
namespace MediaWiki;
use CommentStore;
use Config;
use ConfigFactory;
use CryptHKDF;
@ -761,6 +762,14 @@ class MediaWikiServices extends ServiceContainer {
return $this->getService( 'HttpRequestFactory' );
}
/**
* @since 1.31
* @return CommentStore
*/
public function getCommentStore() {
return $this->getService( 'CommentStore' );
}
///////////////////////////////////////////////////////////////////////////
// NOTE: When adding a service getter here, don't forget to add a test
// case for it in MediaWikiServicesTest::provideGetters() and in

View file

@ -357,7 +357,7 @@ class Revision implements IDBAccessObject {
'rev_sha1',
];
$fields += CommentStore::newKey( 'rev_comment' )->getFields();
$fields += CommentStore::getStore()->getFields( 'rev_comment' );
if ( $wgContentHandlerUseDB ) {
$fields[] = 'rev_content_format';
@ -394,7 +394,7 @@ class Revision implements IDBAccessObject {
'ar_sha1',
];
$fields += CommentStore::newKey( 'ar_comment' )->getFields();
$fields += CommentStore::getStore()->getFields( 'ar_comment' );
if ( $wgContentHandlerUseDB ) {
$fields[] = 'ar_content_format';

View file

@ -523,6 +523,14 @@ return [
return new \MediaWiki\Http\HttpRequestFactory();
},
'CommentStore' => function ( MediaWikiServices $services ) {
global $wgContLang;
return new CommentStore(
$wgContLang,
$services->getMainConfig()->get( 'CommentTableSchemaMigrationStage' )
);
}
///////////////////////////////////////////////////////////////////////////
// NOTE: When adding a service here, don't forget to add a getter function
// in the MediaWikiServices class. The convenience getter should just call

View file

@ -393,7 +393,7 @@ class RevisionStore
}
list( $commentFields, $commentCallback ) =
CommentStore::newKey( 'rev_comment' )->insertWithTempTable( $dbw, $comment );
CommentStore::getStore()->insertWithTempTable( $dbw, 'rev_comment', $comment );
$row += $commentFields;
if ( $this->contentHandlerUseDB ) {
@ -1069,9 +1069,9 @@ class RevisionStore
$user = $this->getUserIdentityFromRowObject( $row, 'ar_' );
$comment = CommentStore::newKey( 'ar_comment' )
$comment = CommentStore::getStore()
// Legacy because $row may have come from self::selectFields()
->getCommentLegacy( $this->getDBConnection( DB_REPLICA ), $row, true );
->getCommentLegacy( $this->getDBConnection( DB_REPLICA ), 'ar_comment', $row, true );
$mainSlot = $this->emulateMainSlot_1_29( $row, $queryFlags, $title );
$slots = new RevisionSlots( [ 'main' => $mainSlot ] );
@ -1139,9 +1139,9 @@ class RevisionStore
$user = $this->getUserIdentityFromRowObject( $row );
$comment = CommentStore::newKey( 'rev_comment' )
$comment = CommentStore::getStore()
// Legacy because $row may have come from self::selectFields()
->getCommentLegacy( $this->getDBConnection( DB_REPLICA ), $row, true );
->getCommentLegacy( $this->getDBConnection( DB_REPLICA ), 'rev_comment', $row, true );
$mainSlot = $this->emulateMainSlot_1_29( $row, $queryFlags, $title );
$slots = new RevisionSlots( [ 'main' => $mainSlot ] );
@ -1614,7 +1614,7 @@ class RevisionStore
'rev_sha1',
] );
$commentQuery = CommentStore::newKey( 'rev_comment' )->getJoin();
$commentQuery = CommentStore::getStore()->getJoin( 'rev_comment' );
$ret['tables'] = array_merge( $ret['tables'], $commentQuery['tables'] );
$ret['fields'] = array_merge( $ret['fields'], $commentQuery['fields'] );
$ret['joins'] = array_merge( $ret['joins'], $commentQuery['joins'] );
@ -1671,7 +1671,7 @@ class RevisionStore
* - joins: (array) to include in the `$join_conds` to `IDatabase->select()`
*/
public function getArchiveQueryInfo() {
$commentQuery = CommentStore::newKey( 'ar_comment' )->getJoin();
$commentQuery = CommentStore::getStore()->getJoin( 'ar_comment' );
$ret = [
'tables' => [ 'archive' ] + $commentQuery['tables'],
'fields' => [

View file

@ -2735,8 +2735,8 @@ class Title implements LinkTarget {
if ( $this->mTitleProtection === null ) {
$dbr = wfGetDB( DB_REPLICA );
$commentStore = new CommentStore( 'pt_reason' );
$commentQuery = $commentStore->getJoin();
$commentStore = CommentStore::getStore();
$commentQuery = $commentStore->getJoin( 'pt_reason' );
$res = $dbr->select(
[ 'protected_titles' ] + $commentQuery['tables'],
[
@ -2757,7 +2757,7 @@ class Title implements LinkTarget {
'user' => $row['user'],
'expiry' => $dbr->decodeExpiry( $row['expiry'] ),
'permission' => $row['permission'],
'reason' => $commentStore->getComment( $row )->text,
'reason' => $commentStore->getComment( 'pt_reason', $row )->text,
];
} else {
$this->mTitleProtection = false;

View file

@ -45,7 +45,7 @@ class ApiQueryAllUsers extends ApiQueryBase {
$activeUserDays = $this->getConfig()->get( 'ActiveUserDays' );
$db = $this->getDB();
$commentStore = new CommentStore( 'ipb_reason' );
$commentStore = CommentStore::getStore();
$prop = $params['prop'];
if ( !is_null( $prop ) ) {
@ -260,7 +260,7 @@ class ApiQueryAllUsers extends ApiQueryBase {
$data['blockedby'] = $row->ipb_by_text;
$data['blockedbyid'] = (int)$row->ipb_by;
$data['blockedtimestamp'] = wfTimestamp( TS_ISO_8601, $row->ipb_timestamp );
$data['blockreason'] = $commentStore->getComment( $row )->text;
$data['blockreason'] = $commentStore->getComment( 'ipb_reason', $row )->text;
$data['blockexpiry'] = $row->ipb_expiry;
}
if ( $row->ipb_deleted ) {

View file

@ -451,7 +451,7 @@ abstract class ApiQueryBase extends ApiBase {
'ipb_expiry',
'ipb_timestamp'
] );
$commentQuery = CommentStore::newKey( 'ipb_reason' )->getJoin();
$commentQuery = CommentStore::getStore()->getJoin( 'ipb_reason' );
$this->addTables( $commentQuery['tables'] );
$this->addFields( $commentQuery['fields'] );
$this->addJoinConds( $commentQuery['joins'] );

View file

@ -33,7 +33,7 @@ class ApiQueryBlocks extends ApiQueryBase {
public function execute() {
$db = $this->getDB();
$commentStore = new CommentStore( 'ipb_reason' );
$commentStore = CommentStore::getStore();
$params = $this->extractRequestParams();
$this->requireMaxOneParameter( $params, 'users', 'ip' );
@ -64,7 +64,7 @@ class ApiQueryBlocks extends ApiQueryBase {
$fld_flags );
if ( $fld_reason ) {
$commentQuery = $commentStore->getJoin();
$commentQuery = $commentStore->getJoin( 'ipb_reason' );
$this->addTables( $commentQuery['tables'] );
$this->addFields( $commentQuery['fields'] );
$this->addJoinConds( $commentQuery['joins'] );
@ -208,7 +208,7 @@ class ApiQueryBlocks extends ApiQueryBase {
$block['expiry'] = ApiResult::formatExpiry( $row->ipb_expiry );
}
if ( $fld_reason ) {
$block['reason'] = $commentStore->getComment( $row )->text;
$block['reason'] = $commentStore->getComment( 'ipb_reason', $row )->text;
}
if ( $fld_range && !$row->ipb_auto ) {
$block['rangestart'] = IP::formatHex( $row->ipb_range_start );

View file

@ -40,7 +40,7 @@ class ApiQueryDeletedrevs extends ApiQueryBase {
$user = $this->getUser();
$db = $this->getDB();
$commentStore = new CommentStore( 'ar_comment' );
$commentStore = CommentStore::getStore();
$params = $this->extractRequestParams( false );
$prop = array_flip( $params['prop'] );
$fld_parentid = isset( $prop['parentid'] );
@ -117,7 +117,7 @@ class ApiQueryDeletedrevs extends ApiQueryBase {
$this->addFieldsIf( 'ar_sha1', $fld_sha1 );
if ( $fld_comment || $fld_parsedcomment ) {
$commentQuery = $commentStore->getJoin();
$commentQuery = $commentStore->getJoin( 'ar_comment' );
$this->addTables( $commentQuery['tables'] );
$this->addFields( $commentQuery['fields'] );
$this->addJoinConds( $commentQuery['joins'] );
@ -325,7 +325,7 @@ class ApiQueryDeletedrevs extends ApiQueryBase {
$anyHidden = true;
}
if ( Revision::userCanBitfield( $row->ar_deleted, Revision::DELETED_COMMENT, $user ) ) {
$comment = $commentStore->getComment( $row )->text;
$comment = $commentStore->getComment( 'ar_comment', $row )->text;
if ( $fld_comment ) {
$rev['comment'] = $comment;
}

View file

@ -41,7 +41,7 @@ class ApiQueryFilearchive extends ApiQueryBase {
$user = $this->getUser();
$db = $this->getDB();
$commentStore = new CommentStore( 'fa_description' );
$commentStore = CommentStore::getStore();
$params = $this->extractRequestParams();
@ -155,7 +155,7 @@ class ApiQueryFilearchive extends ApiQueryBase {
if ( $fld_description &&
Revision::userCanBitfield( $row->fa_deleted, File::DELETED_COMMENT, $user )
) {
$file['description'] = $commentStore->getComment( $row )->text;
$file['description'] = $commentStore->getComment( 'fa_description', $row )->text;
if ( isset( $prop['parseddescription'] ) ) {
$file['parseddescription'] = Linker::formatComment(
$file['description'], $title );

View file

@ -41,7 +41,7 @@ class ApiQueryLogEvents extends ApiQueryBase {
public function execute() {
$params = $this->extractRequestParams();
$db = $this->getDB();
$this->commentStore = new CommentStore( 'log_comment' );
$this->commentStore = CommentStore::getStore();
$this->requireMaxOneParameter( $params, 'title', 'prefix', 'namespace' );
$prop = array_flip( $params['prop'] );
@ -93,7 +93,7 @@ class ApiQueryLogEvents extends ApiQueryBase {
$this->addFieldsIf( 'log_params', $this->fld_details );
if ( $this->fld_comment || $this->fld_parsedcomment ) {
$commentQuery = $this->commentStore->getJoin();
$commentQuery = $this->commentStore->getJoin( 'log_comment' );
$this->addTables( $commentQuery['tables'] );
$this->addFields( $commentQuery['fields'] );
$this->addJoinConds( $commentQuery['joins'] );
@ -338,7 +338,7 @@ class ApiQueryLogEvents extends ApiQueryBase {
$anyHidden = true;
}
if ( LogEventsList::userCan( $row, LogPage::DELETED_COMMENT, $user ) ) {
$comment = $this->commentStore->getComment( $row )->text;
$comment = $this->commentStore->getComment( 'log_comment', $row )->text;
if ( $this->fld_comment ) {
$vals['comment'] = $comment;
}

View file

@ -55,8 +55,8 @@ class ApiQueryProtectedTitles extends ApiQueryGeneratorBase {
$this->addFieldsIf( 'pt_create_perm', isset( $prop['level'] ) );
if ( isset( $prop['comment'] ) || isset( $prop['parsedcomment'] ) ) {
$commentStore = new CommentStore( 'pt_reason' );
$commentQuery = $commentStore->getJoin();
$commentStore = CommentStore::getStore();
$commentQuery = $commentStore->getJoin( 'pt_reason' );
$this->addTables( $commentQuery['tables'] );
$this->addFields( $commentQuery['fields'] );
$this->addJoinConds( $commentQuery['joins'] );
@ -130,12 +130,12 @@ class ApiQueryProtectedTitles extends ApiQueryGeneratorBase {
}
if ( isset( $prop['comment'] ) ) {
$vals['comment'] = $commentStore->getComment( $row )->text;
$vals['comment'] = $commentStore->getComment( 'pt_reason', $row )->text;
}
if ( isset( $prop['parsedcomment'] ) ) {
$vals['parsedcomment'] = Linker::formatComment(
$commentStore->getComment( $row )->text, $titles
$commentStore->getComment( 'pt_reason', $row )->text, $titles
);
}

View file

@ -350,8 +350,8 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
$this->token = $params['token'];
if ( $this->fld_comment || $this->fld_parsedcomment || $this->token ) {
$this->commentStore = new CommentStore( 'rc_comment' );
$commentQuery = $this->commentStore->getJoin();
$this->commentStore = CommentStore::getStore();
$commentQuery = $this->commentStore->getJoin( 'rc_comment' );
$this->addTables( $commentQuery['tables'] );
$this->addFields( $commentQuery['fields'] );
$this->addJoinConds( $commentQuery['joins'] );
@ -506,7 +506,7 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
$anyHidden = true;
}
if ( Revision::userCanBitfield( $row->rc_deleted, Revision::DELETED_COMMENT, $user ) ) {
$comment = $this->commentStore->getComment( $row )->text;
$comment = $this->commentStore->getComment( 'rc_comment', $row )->text;
if ( $this->fld_comment ) {
$vals['comment'] = $comment;
}

View file

@ -41,7 +41,7 @@ class ApiQueryContributions extends ApiQueryBase {
// Parse some parameters
$this->params = $this->extractRequestParams();
$this->commentStore = new CommentStore( 'rev_comment' );
$this->commentStore = CommentStore::getStore();
$prop = array_flip( $this->params['prop'] );
$this->fld_ids = isset( $prop['ids'] );
@ -345,7 +345,7 @@ class ApiQueryContributions extends ApiQueryBase {
$this->addFieldsIf( 'rc_patrolled', $this->fld_patrolled );
if ( $this->fld_comment || $this->fld_parsedcomment ) {
$commentQuery = $this->commentStore->getJoin();
$commentQuery = $this->commentStore->getJoin( 'rev_comment' );
$this->addTables( $commentQuery['tables'] );
$this->addFields( $commentQuery['fields'] );
$this->addJoinConds( $commentQuery['joins'] );
@ -432,7 +432,7 @@ class ApiQueryContributions extends ApiQueryBase {
);
if ( $userCanView ) {
$comment = $this->commentStore->getComment( $row )->text;
$comment = $this->commentStore->getComment( 'rev_comment', $row )->text;
if ( $this->fld_comment ) {
$vals['comment'] = $comment;
}

View file

@ -95,7 +95,7 @@ class ApiQueryUsers extends ApiQueryBase {
public function execute() {
$db = $this->getDB();
$commentStore = new CommentStore( 'ipb_reason' );
$commentStore = CommentStore::getStore();
$params = $this->extractRequestParams();
$this->requireMaxOneParameter( $params, 'userids', 'users' );
@ -235,7 +235,8 @@ class ApiQueryUsers extends ApiQueryBase {
$data[$key]['blockedby'] = $row->ipb_by_text;
$data[$key]['blockedbyid'] = (int)$row->ipb_by;
$data[$key]['blockedtimestamp'] = wfTimestamp( TS_ISO_8601, $row->ipb_timestamp );
$data[$key]['blockreason'] = $commentStore->getComment( $row )->text;
$data[$key]['blockreason'] = $commentStore->getComment( 'ipb_reason', $row )
->text;
$data[$key]['blockexpiry'] = $row->ipb_expiry;
}

View file

@ -87,7 +87,7 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase {
}
if ( $this->fld_comment || $this->fld_parsedcomment ) {
$this->commentStore = new CommentStore( 'rc_comment' );
$this->commentStore = CommentStore::getStore();
}
}
@ -357,7 +357,7 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase {
Revision::DELETED_COMMENT,
$user
) ) {
$comment = $this->commentStore->getComment( $recentChangeInfo )->text;
$comment = $this->commentStore->getComment( 'rc_comment', $recentChangeInfo )->text;
if ( $this->fld_comment ) {
$vals['comment'] = $comment;
}

View file

@ -235,7 +235,7 @@ class RecentChange {
'rc_log_type',
'rc_log_action',
'rc_params',
] + CommentStore::newKey( 'rc_comment' )->getFields();
] + CommentStore::getStore()->getFields( 'rc_comment' );
}
/**
@ -248,7 +248,7 @@ class RecentChange {
* - joins: (array) to include in the `$join_conds` to `IDatabase->select()`
*/
public static function getQueryInfo() {
$commentQuery = CommentStore::newKey( 'rc_comment' )->getJoin();
$commentQuery = CommentStore::getStore()->getJoin( 'rc_comment' );
return [
'tables' => [ 'recentchanges' ] + $commentQuery['tables'],
'fields' => [
@ -372,7 +372,7 @@ class RecentChange {
$row = $this->mAttribs;
$comment = $row['rc_comment'];
unset( $row['rc_comment'], $row['rc_comment_text'], $row['rc_comment_data'] );
$row += CommentStore::newKey( 'rc_comment' )->insert( $dbw, $comment );
$row += CommentStore::getStore()->insert( $dbw, 'rc_comment', $comment );
# Don't reuse an existing rc_id for the new row, if one happens to be
# set for some reason.
@ -995,9 +995,10 @@ class RecentChange {
}
}
$comment = CommentStore::newKey( 'rc_comment' )
$comment = CommentStore::getStore()
// Legacy because $row may have come from self::selectFields()
->getCommentLegacy( wfGetDB( DB_REPLICA ), $row, true )->text;
->getCommentLegacy( wfGetDB( DB_REPLICA ), 'rc_comment', $row, true )
->text;
$this->mAttribs['rc_comment'] = &$comment;
$this->mAttribs['rc_comment_text'] = &$comment;
$this->mAttribs['rc_comment_data'] = null;
@ -1011,7 +1012,8 @@ class RecentChange {
*/
public function getAttribute( $name ) {
if ( $name === 'rc_comment' ) {
return CommentStore::newKey( 'rc_comment' )->getComment( $this->mAttribs, true )->text;
return CommentStore::getStore()
->getComment( 'rc_comment', $this->mAttribs, true )->text;
}
return isset( $this->mAttribs[$name] ) ? $this->mAttribs[$name] : null;
}

View file

@ -278,7 +278,7 @@ class WikiExporter {
}
$result = null; // Assuring $result is not undefined, if exception occurs early
$commentQuery = CommentStore::newKey( 'log_comment' )->getJoin();
$commentQuery = CommentStore::getStore()->getJoin( 'log_comment' );
try {
$result = $this->db->select( [ 'logging', 'user' ] + $commentQuery['tables'],
@ -399,7 +399,7 @@ class WikiExporter {
Hooks::run( 'ModifyExportQuery',
[ $this->db, &$tables, &$cond, &$opts, &$join ] );
$commentQuery = CommentStore::newKey( 'rev_comment' )->getJoin();
$commentQuery = CommentStore::getStore()->getJoin( 'rev_comment' );
# Do the query!
$result = $this->db->select(

View file

@ -219,7 +219,7 @@ class XmlDumpWriter {
if ( isset( $row->rev_deleted ) && ( $row->rev_deleted & Revision::DELETED_COMMENT ) ) {
$out .= " " . Xml::element( 'comment', [ 'deleted' => 'deleted' ] ) . "\n";
} else {
$comment = CommentStore::newKey( 'rev_comment' )->getComment( $row )->text;
$comment = CommentStore::getStore()->getComment( 'rev_comment', $row )->text;
if ( $comment != '' ) {
$out .= " " . Xml::elementClean( 'comment', [], strval( $comment ) ) . "\n";
}
@ -303,7 +303,7 @@ class XmlDumpWriter {
if ( $row->log_deleted & LogPage::DELETED_COMMENT ) {
$out .= " " . Xml::element( 'comment', [ 'deleted' => 'deleted' ] ) . "\n";
} else {
$comment = CommentStore::newKey( 'log_comment' )->getComment( $row )->text;
$comment = CommentStore::getStore()->getComment( 'log_comment', $row )->text;
if ( $comment != '' ) {
$out .= " " . Xml::elementClean( 'comment', null, strval( $comment ) ) . "\n";
}

View file

@ -242,7 +242,7 @@ class ArchivedFile {
'fa_deleted',
'fa_deleted_timestamp', /* Used by LocalFileRestoreBatch */
'fa_sha1',
] + CommentStore::newKey( 'fa_description' )->getFields();
] + CommentStore::getStore()->getFields( 'fa_description' );
}
/**
@ -255,7 +255,7 @@ class ArchivedFile {
* - joins: (array) to include in the `$join_conds` to `IDatabase->select()`
*/
public static function getQueryInfo() {
$commentQuery = CommentStore::newKey( 'fa_description' )->getJoin();
$commentQuery = CommentStore::getStore()->getJoin( 'fa_description' );
return [
'tables' => [ 'filearchive' ] + $commentQuery['tables'],
'fields' => [
@ -302,9 +302,9 @@ class ArchivedFile {
$this->metadata = $row->fa_metadata;
$this->mime = "$row->fa_major_mime/$row->fa_minor_mime";
$this->media_type = $row->fa_media_type;
$this->description = CommentStore::newKey( 'fa_description' )
$this->description = CommentStore::getStore()
// Legacy because $row may have come from self::selectFields()
->getCommentLegacy( wfGetDB( DB_REPLICA ), $row )->text;
->getCommentLegacy( wfGetDB( DB_REPLICA ), 'fa_description', $row )->text;
$this->user = $row->fa_user;
$this->user_text = $row->fa_user_text;
$this->timestamp = $row->fa_timestamp;

View file

@ -215,7 +215,7 @@ class LocalFile extends File {
'img_user_text',
'img_timestamp',
'img_sha1',
] + CommentStore::newKey( 'img_description' )->getFields();
] + CommentStore::getStore()->getFields( 'img_description' );
}
/**
@ -230,7 +230,7 @@ class LocalFile extends File {
* - joins: (array) to include in the `$join_conds` to `IDatabase->select()`
*/
public static function getQueryInfo( array $options = [] ) {
$commentQuery = CommentStore::newKey( 'img_description' )->getJoin();
$commentQuery = CommentStore::getStore()->getJoin( 'img_description' );
$ret = [
'tables' => [ 'image' ] + $commentQuery['tables'],
'fields' => [
@ -566,8 +566,8 @@ class LocalFile extends File {
function decodeRow( $row, $prefix = 'img_' ) {
$decoded = $this->unprefixRow( $row, $prefix );
$decoded['description'] = CommentStore::newKey( 'description' )
->getComment( (object)$decoded )->text;
$decoded['description'] = CommentStore::getStore()
->getComment( 'description', (object)$decoded )->text;
$decoded['timestamp'] = wfTimestamp( TS_MW, $decoded['timestamp'] );
@ -1424,9 +1424,9 @@ class LocalFile extends File {
# Test to see if the row exists using INSERT IGNORE
# This avoids race conditions by locking the row until the commit, and also
# doesn't deadlock. SELECT FOR UPDATE causes a deadlock for every race condition.
$commentStore = new CommentStore( 'img_description' );
$commentStore = CommentStore::getStore();
list( $commentFields, $commentCallback ) =
$commentStore->insertWithTempTable( $dbw, $comment );
$commentStore->insertWithTempTable( $dbw, 'img_description', $comment );
$dbw->insert( 'image',
[
'img_name' => $this->getName(),
@ -1522,7 +1522,9 @@ class LocalFile extends File {
[ 'image_comment_temp' => [ 'LEFT JOIN', [ 'imgcomment_name = img_name' ] ] ]
);
foreach ( $res as $row ) {
list( , $callback ) = $commentStore->insertWithTempTable( $dbw, $row->img_description );
list( , $callback ) = $commentStore->insertWithTempTable(
$dbw, 'img_description', $row->img_description
);
$callback( $row->img_name );
}
}
@ -2403,10 +2405,7 @@ class LocalFileDeleteBatch {
$now = time();
$dbw = $this->file->repo->getMasterDB();
$commentStoreImgDesc = new CommentStore( 'img_description' );
$commentStoreOiDesc = new CommentStore( 'oi_description' );
$commentStoreFaDesc = new CommentStore( 'fa_description' );
$commentStoreFaReason = new CommentStore( 'fa_deleted_reason' );
$commentStore = CommentStore::getStore();
$encTimestamp = $dbw->addQuotes( $dbw->timestamp( $now ) );
$encUserId = $dbw->addQuotes( $this->user->getId() );
@ -2454,7 +2453,7 @@ class LocalFileDeleteBatch {
$fields += array_map(
[ $dbw, 'addQuotes' ],
$commentStoreFaReason->insert( $dbw, $this->reason )
$commentStore->insert( $dbw, 'fa_deleted_reason', $this->reason )
);
if ( $wgCommentTableSchemaMigrationStage <= MIGRATION_WRITE_BOTH ) {
@ -2484,7 +2483,9 @@ class LocalFileDeleteBatch {
[ 'image_comment_temp' => [ 'LEFT JOIN', [ 'imgcomment_name = img_name' ] ] ]
);
foreach ( $res as $row ) {
list( , $callback ) = $commentStoreImgDesc->insertWithTempTable( $dbw, $row->img_description );
list( , $callback ) = $commentStore->insertWithTempTable(
$dbw, 'img_description', $row->img_description
);
$callback( $row->img_name );
}
}
@ -2508,9 +2509,9 @@ class LocalFileDeleteBatch {
);
$rowsInsert = [];
if ( $res->numRows() ) {
$reason = $commentStoreFaReason->createComment( $dbw, $this->reason );
$reason = $commentStore->createComment( $dbw, 'fa_deleted_reason', $this->reason );
foreach ( $res as $row ) {
$comment = $commentStoreOiDesc->getComment( $row );
$comment = $commentStore->getComment( 'oi_description', $row );
$rowsInsert[] = [
// Deletion-specific fields
'fa_storage_group' => 'deleted',
@ -2535,8 +2536,8 @@ class LocalFileDeleteBatch {
'fa_user_text' => $row->oi_user_text,
'fa_timestamp' => $row->oi_timestamp,
'fa_sha1' => $row->oi_sha1
] + $commentStoreFaReason->insert( $dbw, $reason )
+ $commentStoreFaDesc->insert( $dbw, $comment );
] + $commentStore->insert( $dbw, 'fa_deleted_reason', $reason )
+ $commentStore->insert( $dbw, 'fa_description', $comment );
}
}
@ -2734,9 +2735,7 @@ class LocalFileRestoreBatch {
$dbw = $this->file->repo->getMasterDB();
$commentStoreImgDesc = new CommentStore( 'img_description' );
$commentStoreOiDesc = new CommentStore( 'oi_description' );
$commentStoreFaDesc = new CommentStore( 'fa_description' );
$commentStore = CommentStore::getStore();
$status = $this->file->repo->newGood();
@ -2824,12 +2823,12 @@ class LocalFileRestoreBatch {
];
}
$comment = $commentStoreFaDesc->getComment( $row );
$comment = $commentStore->getComment( 'fa_description', $row );
if ( $first && !$exists ) {
// This revision will be published as the new current version
$destRel = $this->file->getRel();
list( $commentFields, $commentCallback ) =
$commentStoreImgDesc->insertWithTempTable( $dbw, $comment );
$commentStore->insertWithTempTable( $dbw, 'img_description', $comment );
$insertCurrent = [
'img_name' => $row->fa_name,
'img_size' => $row->fa_size,
@ -2885,7 +2884,7 @@ class LocalFileRestoreBatch {
'oi_minor_mime' => $props['minor_mime'],
'oi_deleted' => $this->unsuppress ? 0 : $row->fa_deleted,
'oi_sha1' => $sha1
] + $commentStoreOiDesc->insert( $dbw, $comment );
] + $commentStore->insert( $dbw, 'oi_description', $comment );
}
$deleteIds[] = $row->fa_id;

View file

@ -127,7 +127,7 @@ class OldLocalFile extends LocalFile {
'oi_timestamp',
'oi_deleted',
'oi_sha1',
] + CommentStore::newKey( 'oi_description' )->getFields();
] + CommentStore::getStore()->getFields( 'oi_description' );
}
/**
@ -142,7 +142,7 @@ class OldLocalFile extends LocalFile {
* - joins: (array) to include in the `$join_conds` to `IDatabase->select()`
*/
public static function getQueryInfo( array $options = [] ) {
$commentQuery = CommentStore::newKey( 'oi_description' )->getJoin();
$commentQuery = CommentStore::getStore()->getJoin( 'oi_description' );
$ret = [
'tables' => [ 'oldimage' ] + $commentQuery['tables'],
'fields' => [
@ -434,7 +434,7 @@ class OldLocalFile extends LocalFile {
return false;
}
$commentFields = CommentStore::newKey( 'oi_description' )->insert( $dbw, $comment );
$commentFields = CommentStore::getStore()->insert( $dbw, 'oi_description', $comment );
$dbw->insert( 'oldimage',
[
'oi_name' => $this->getName(),

View file

@ -729,7 +729,7 @@ class WikiRevision {
'log_namespace' => $this->getTitle()->getNamespace(),
'log_title' => $this->getTitle()->getDBkey(),
'log_params' => $this->params
] + CommentStore::newKey( 'log_comment' )->insert( $dbw, $this->getComment() );
] + CommentStore::getStore()->insert( $dbw, 'log_comment', $this->getComment() );
$dbw->insert( 'logging', $data, __METHOD__ );
return true;

View file

@ -170,7 +170,7 @@ class DatabaseLogEntry extends LogEntryBase {
* @return array
*/
public static function getSelectQueryData() {
$commentQuery = CommentStore::newKey( 'log_comment' )->getJoin();
$commentQuery = CommentStore::getStore()->getJoin( 'log_comment' );
$tables = [ 'logging', 'user' ] + $commentQuery['tables'];
$fields = [
@ -324,7 +324,7 @@ class DatabaseLogEntry extends LogEntryBase {
}
public function getComment() {
return CommentStore::newKey( 'log_comment' )->getComment( $this->row )->text;
return CommentStore::getStore()->getComment( 'log_comment', $this->row )->text;
}
public function getDeleted() {
@ -382,9 +382,9 @@ class RCDatabaseLogEntry extends DatabaseLogEntry {
}
public function getComment() {
return CommentStore::newKey( 'rc_comment' )
return CommentStore::getStore()
// Legacy because the row may have used RecentChange::selectFields()
->getCommentLegacy( wfGetDB( DB_REPLICA ), $this->row )->text;
->getCommentLegacy( wfGetDB( DB_REPLICA ), 'rc_comment', $this->row )->text;
}
public function getDeleted() {
@ -626,7 +626,7 @@ class ManualLogEntry extends LogEntryBase {
if ( isset( $this->deleted ) ) {
$data['log_deleted'] = $this->deleted;
}
$data += CommentStore::newKey( 'log_comment' )->insert( $dbw, $comment );
$data += CommentStore::getStore()->insert( $dbw, 'log_comment', $comment );
$dbw->insert( 'logging', $data, __METHOD__ );
$this->id = $dbw->insertId();

View file

@ -104,7 +104,7 @@ class LogPage {
'log_page' => $this->target->getArticleID(),
'log_params' => $this->params
];
$data += CommentStore::newKey( 'log_comment' )->insert( $dbw, $this->comment );
$data += CommentStore::getStore()->insert( $dbw, 'log_comment', $this->comment );
$dbw->insert( 'logging', $data, __METHOD__ );
$newId = $dbw->insertId();

View file

@ -2517,7 +2517,7 @@ class WikiPage implements Page, IDBAccessObject {
$cascade = false;
if ( $limit['create'] != '' ) {
$commentFields = CommentStore::newKey( 'pt_reason' )->insert( $dbw, $reason );
$commentFields = CommentStore::getStore()->insert( $dbw, 'pt_reason', $reason );
$dbw->replace( 'protected_titles',
[ [ 'pt_namespace', 'pt_title' ] ],
[
@ -2844,8 +2844,7 @@ class WikiPage implements Page, IDBAccessObject {
$content = null;
}
$revCommentStore = new CommentStore( 'rev_comment' );
$arCommentStore = new CommentStore( 'ar_comment' );
$commentStore = CommentStore::getStore();
$revQuery = Revision::getQueryInfo();
$bitfield = false;
@ -2881,7 +2880,7 @@ class WikiPage implements Page, IDBAccessObject {
$ipRevIds = [];
foreach ( $res as $row ) {
$comment = $revCommentStore->getComment( $row );
$comment = $commentStore->getComment( 'rev_comment', $row );
$rowInsert = [
'ar_namespace' => $namespace,
'ar_title' => $dbKey,
@ -2898,7 +2897,7 @@ class WikiPage implements Page, IDBAccessObject {
'ar_page_id' => $id,
'ar_deleted' => $suppress ? $bitfield : $row->rev_deleted,
'ar_sha1' => $row->rev_sha1,
] + $arCommentStore->insert( $dbw, $comment );
] + $commentStore->insert( $dbw, 'ar_comment', $comment );
if ( $wgContentHandlerUseDB ) {
$rowInsert['ar_content_model'] = $row->rev_content_model;
$rowInsert['ar_content_format'] = $row->rev_content_format;

View file

@ -94,7 +94,7 @@ class IRCColourfulRCFeedFormatter implements RCFeedFormatter {
$flag = $attribs['rc_log_action'];
} else {
$comment = self::cleanupForIRC(
CommentStore::newKey( 'rc_comment' )->getComment( $attribs )->text
CommentStore::getStore()->getComment( 'rc_comment', $attribs )->text
);
$flag = '';
if ( !$attribs['rc_patrolled']

View file

@ -102,7 +102,7 @@ class RevDelLogItem extends RevDelItem {
// User links and action text
$action = $formatter->getActionText();
// Comment
$comment = CommentStore::newKey( 'log_comment' )->getComment( $this->row )->text;
$comment = CommentStore::getStore()->getComment( 'log_comment', $this->row )->text;
$comment = $this->list->getLanguage()->getDirMark()
. Linker::commentBlock( $comment );
@ -136,7 +136,8 @@ class RevDelLogItem extends RevDelItem {
}
if ( LogEventsList::userCan( $this->row, LogPage::DELETED_COMMENT, $user ) ) {
$ret += [
'comment' => CommentStore::newKey( 'log_comment' )->getComment( $this->row )->text,
'comment' => CommentStore::getStore()->getComment( 'log_comment', $this->row )
->text,
];
}

View file

@ -63,7 +63,7 @@ class RevDelLogList extends RevDelList {
public function doQuery( $db ) {
$ids = array_map( 'intval', $this->ids );
$commentQuery = CommentStore::newKey( 'log_comment' )->getJoin();
$commentQuery = CommentStore::getStore()->getJoin( 'log_comment' );
return $db->select(
[ 'logging' ] + $commentQuery['tables'],

View file

@ -295,7 +295,7 @@ class SpecialNewpages extends IncludableSpecialPage {
*/
protected function revisionFromRcResult( stdClass $result, Title $title ) {
return new Revision( [
'comment' => CommentStore::newKey( 'rc_comment' )->getComment( $result )->text,
'comment' => CommentStore::getStore()->getComment( 'rc_comment', $result )->text,
'deleted' => $result->rc_deleted,
'user_text' => $result->rc_user_text,
'user' => $result->rc_user,

View file

@ -173,7 +173,7 @@ class BlockListPager extends TablePager {
break;
case 'ipb_reason':
$value = CommentStore::newKey( 'ipb_reason' )->getComment( $row )->text;
$value = CommentStore::getStore()->getComment( 'ipb_reason', $row )->text;
$formatted = Linker::formatComment( $value );
break;
@ -209,7 +209,7 @@ class BlockListPager extends TablePager {
}
function getQueryInfo() {
$commentQuery = CommentStore::newKey( 'ipb_reason' )->getJoin();
$commentQuery = CommentStore::getStore()->getJoin( 'ipb_reason' );
$info = [
'tables' => [ 'ipblocks', 'user' ] + $commentQuery['tables'],

View file

@ -69,7 +69,7 @@ class DeletedContribsPager extends IndexPager {
' != ' . Revision::SUPPRESSED_USER;
}
$commentQuery = CommentStore::newKey( 'ar_comment' )->getJoin();
$commentQuery = CommentStore::getStore()->getJoin( 'ar_comment' );
return [
'tables' => [ 'archive' ] + $commentQuery['tables'],
@ -256,7 +256,7 @@ class DeletedContribsPager extends IndexPager {
$rev = new Revision( [
'title' => $page,
'id' => $row->ar_rev_id,
'comment' => CommentStore::newKey( 'ar_comment' )->getComment( $row )->text,
'comment' => CommentStore::getStore()->getComment( 'ar_comment', $row )->text,
'user' => $row->ar_user,
'user_text' => $row->ar_user_text,
'timestamp' => $row->ar_timestamp,

View file

@ -267,7 +267,7 @@ class ImageListPager extends TablePager {
$options = $join_conds = [];
# Description field
$commentQuery = CommentStore::newKey( $prefix . '_description' )->getJoin();
$commentQuery = CommentStore::getStore()->getJoin( $prefix . '_description' );
$tables += $commentQuery['tables'];
$fields += $commentQuery['fields'];
$join_conds += $commentQuery['joins'];
@ -498,7 +498,7 @@ class ImageListPager extends TablePager {
return htmlspecialchars( $this->getLanguage()->formatSize( $value ) );
case 'img_description':
$field = $this->mCurrentRow->description_field;
$value = CommentStore::newKey( $field )->getComment( $this->mCurrentRow )->text;
$value = CommentStore::getStore()->getComment( $field, $this->mCurrentRow )->text;
return Linker::formatComment( $value );
case 'count':
return $this->getLanguage()->formatNum( intval( $value ) + 1 );

View file

@ -90,7 +90,7 @@ class NewPagesPager extends ReverseChronologicalPager {
$conds['page_is_redirect'] = 0;
}
$commentQuery = CommentStore::newKey( 'rc_comment' )->getJoin();
$commentQuery = CommentStore::getStore()->getJoin( 'rc_comment' );
// Allow changes to the New Pages query
$tables = [ 'recentchanges', 'page' ] + $commentQuery['tables'];

View file

@ -234,7 +234,7 @@ class ProtectedPagesPager extends TablePager {
LogPage::DELETED_COMMENT,
$this->getUser()
) ) {
$value = CommentStore::newKey( 'log_comment' )->getComment( $row )->text;
$value = CommentStore::getStore()->getComment( 'log_comment', $row )->text;
$formatted = Linker::formatComment( $value !== null ? $value : '' );
} else {
$formatted = $this->msg( 'rev-deleted-comment' )->escaped();
@ -283,7 +283,7 @@ class ProtectedPagesPager extends TablePager {
$conds[] = 'page_namespace=' . $this->mDb->addQuotes( $this->namespace );
}
$commentQuery = CommentStore::newKey( 'log_comment' )->getJoin();
$commentQuery = CommentStore::getStore()->getJoin( 'log_comment' );
return [
'tables' => [ 'page', 'page_restrictions', 'log_search', 'logging' ] + $commentQuery['tables'],

View file

@ -56,12 +56,12 @@ class WatchedItemQueryService {
/** @var WatchedItemQueryServiceExtension[]|null */
private $extensions = null;
/**
* @var CommentStore|null */
private $commentStore = null;
/** @var CommentStore */
private $commentStore;
public function __construct( LoadBalancer $loadBalancer ) {
$this->loadBalancer = $loadBalancer;
$this->commentStore = CommentStore::getStore();
}
/**
@ -83,13 +83,6 @@ class WatchedItemQueryService {
return $this->loadBalancer->getConnectionRef( DB_REPLICA, [ 'watchlist' ] );
}
private function getCommentStore() {
if ( !$this->commentStore ) {
$this->commentStore = new CommentStore( 'rc_comment' );
}
return $this->commentStore;
}
/**
* @param User $user
* @param array $options Allowed keys:
@ -334,7 +327,7 @@ class WatchedItemQueryService {
$tables[] = 'page';
}
if ( in_array( self::INCLUDE_COMMENT, $options['includeFields'] ) ) {
$tables += $this->getCommentStore()->getJoin()['tables'];
$tables += $this->commentStore->getJoin( 'rc_comment' )['tables'];
}
if ( in_array( self::INCLUDE_TAGS, $options['includeFields'] ) ) {
$tables[] = 'tag_summary';
@ -377,7 +370,7 @@ class WatchedItemQueryService {
$fields[] = 'rc_user';
}
if ( in_array( self::INCLUDE_COMMENT, $options['includeFields'] ) ) {
$fields += $this->getCommentStore()->getJoin()['fields'];
$fields += $this->commentStore->getJoin( 'rc_comment' )['fields'];
}
if ( in_array( self::INCLUDE_PATROL_INFO, $options['includeFields'] ) ) {
$fields = array_merge( $fields, [ 'rc_patrolled', 'rc_log_type' ] );
@ -684,7 +677,7 @@ class WatchedItemQueryService {
$joinConds['page'] = [ 'LEFT JOIN', 'rc_cur_id=page_id' ];
}
if ( in_array( self::INCLUDE_COMMENT, $options['includeFields'] ) ) {
$joinConds += $this->getCommentStore()->getJoin()['joins'];
$joinConds += $this->commentStore->getJoin( 'rc_comment' )['joins'];
}
if ( in_array( self::INCLUDE_TAGS, $options['includeFields'] ) ) {
$joinConds['tag_summary'] = [ 'LEFT JOIN', [ 'rc_id=ts_rc_id' ] ];

View file

@ -75,13 +75,13 @@ class Orphans extends Maintenance {
*/
private function checkOrphans( $fix ) {
$dbw = $this->getDB( DB_MASTER );
$commentStore = new CommentStore( 'rev_comment' );
$commentStore = CommentStore::getStore();
if ( $fix ) {
$this->lockTables( $dbw );
}
$commentQuery = $commentStore->getJoin();
$commentQuery = $commentStore->getJoin( 'rev_comment' );
$this->output( "Checking for orphan revision table entries... "
. "(this may take a while on a large wiki)\n" );
@ -104,7 +104,7 @@ class Orphans extends Maintenance {
) );
foreach ( $result as $row ) {
$comment = $commentStore->getComment( $row )->text;
$comment = $commentStore->getComment( 'rev_comment', $row )->text;
if ( $comment !== '' ) {
$comment = '(' . $wgContLang->truncate( $comment, 40 ) . ')';
}

View file

@ -80,8 +80,7 @@ class RebuildRecentchanges extends Maintenance {
*/
private function rebuildRecentChangesTablePass1() {
$dbw = $this->getDB( DB_MASTER );
$revCommentStore = new CommentStore( 'rev_comment' );
$rcCommentStore = new CommentStore( 'rc_comment' );
$commentStore = CommentStore::getStore();
if ( $this->hasOption( 'from' ) && $this->hasOption( 'to' ) ) {
$this->cutoffFrom = wfTimestamp( TS_UNIX, $this->getOption( 'from' ) );
@ -116,7 +115,7 @@ class RebuildRecentchanges extends Maintenance {
$this->output( "Loading from page and revision tables...\n" );
$commentQuery = $revCommentStore->getJoin();
$commentQuery = $commentStore->getJoin( 'rev_comment' );
$res = $dbw->select(
[ 'revision', 'page' ] + $commentQuery['tables'],
[
@ -145,7 +144,7 @@ class RebuildRecentchanges extends Maintenance {
$this->output( "Inserting from page and revision tables...\n" );
$inserted = 0;
foreach ( $res as $row ) {
$comment = $revCommentStore->getComment( $row );
$comment = $commentStore->getComment( 'rev_comment', $row );
$dbw->insert(
'recentchanges',
[
@ -163,7 +162,7 @@ class RebuildRecentchanges extends Maintenance {
'rc_type' => $row->page_is_new ? RC_NEW : RC_EDIT,
'rc_source' => $row->page_is_new ? RecentChange::SRC_NEW : RecentChange::SRC_EDIT,
'rc_deleted' => $row->rev_deleted
] + $rcCommentStore->insert( $dbw, $comment ),
] + $commentStore->insert( $dbw, 'rc_comment', $comment ),
__METHOD__
);
if ( ( ++$inserted % $this->getBatchSize() ) == 0 ) {
@ -270,12 +269,11 @@ class RebuildRecentchanges extends Maintenance {
global $wgLogTypes, $wgLogRestrictions;
$dbw = $this->getDB( DB_MASTER );
$logCommentStore = new CommentStore( 'log_comment' );
$rcCommentStore = new CommentStore( 'rc_comment' );
$commentStore = CommentStore::getStore();
$this->output( "Loading from user, page, and logging tables...\n" );
$commentQuery = $logCommentStore->getJoin();
$commentQuery = $commentStore->getJoin( 'log_comment' );
$res = $dbw->select(
[ 'user', 'logging', 'page' ] + $commentQuery['tables'],
[
@ -311,7 +309,7 @@ class RebuildRecentchanges extends Maintenance {
$inserted = 0;
foreach ( $res as $row ) {
$comment = $logCommentStore->getComment( $row );
$comment = $commentStore->getComment( 'log_comment', $row );
$dbw->insert(
'recentchanges',
[
@ -336,7 +334,7 @@ class RebuildRecentchanges extends Maintenance {
'rc_logid' => $row->log_id,
'rc_params' => $row->log_params,
'rc_deleted' => $row->log_deleted
] + $rcCommentStore->insert( $dbw, $comment ),
] + $commentStore->insert( $dbw, 'rc_comment', $comment ),
__METHOD__
);

View file

@ -20,11 +20,22 @@ class CommentStoreTest extends MediaWikiLangTestCase {
/**
* Create a store for a particular stage
* @param int $stage
* @return CommentStore
*/
protected function makeStore( $stage ) {
global $wgContLang;
$store = new CommentStore( $wgContLang, $stage );
return $store;
}
/**
* Create a store for a particular stage and key (for testing deprecated behaviour)
* @param int $stage
* @param string $key
* @return CommentStore
*/
protected function makeStore( $stage, $key ) {
$store = new CommentStore( $key );
protected function makeStoreWithKey( $stage, $key ) {
$store = CommentStore::newKey( $key );
TestingAccessWrapper::newFromObject( $store )->stage = $stage;
return $store;
}
@ -35,12 +46,24 @@ class CommentStoreTest extends MediaWikiLangTestCase {
* @param string $key
* @param array $expect
*/
public function testGetFields( $stage, $key, $expect ) {
$store = $this->makeStore( $stage, $key );
public function testGetFields_withKeyConstruction( $stage, $key, $expect ) {
$store = $this->makeStoreWithKey( $stage, $key );
$result = $store->getFields();
$this->assertEquals( $expect, $result );
}
/**
* @dataProvider provideGetFields
* @param int $stage
* @param string $key
* @param array $expect
*/
public function testGetFields( $stage, $key, $expect ) {
$store = $this->makeStore( $stage );
$result = $store->getFields( $key );
$this->assertEquals( $expect, $result );
}
public static function provideGetFields() {
return [
'Simple table, old' => [
@ -110,12 +133,24 @@ class CommentStoreTest extends MediaWikiLangTestCase {
* @param string $key
* @param array $expect
*/
public function testGetJoin( $stage, $key, $expect ) {
$store = $this->makeStore( $stage, $key );
public function testGetJoin_withKeyConstruction( $stage, $key, $expect ) {
$store = $this->makeStoreWithKey( $stage, $key );
$result = $store->getJoin();
$this->assertEquals( $expect, $result );
}
/**
* @dataProvider provideGetJoin
* @param int $stage
* @param string $key
* @param array $expect
*/
public function testGetJoin( $stage, $key, $expect ) {
$store = $this->makeStore( $stage );
$result = $store->getJoin( $key );
$this->assertEquals( $expect, $result );
}
public static function provideGetJoin() {
return [
'Simple table, old' => [
@ -343,11 +378,106 @@ class CommentStoreTest extends MediaWikiLangTestCase {
$extraFields['ipb_address'] = __CLASS__ . "#$writeStage";
}
$wstore = $this->makeStore( $writeStage, $key );
$wstore = $this->makeStore( $writeStage );
$usesTemp = $key === 'rev_comment';
if ( $usesTemp ) {
list( $fields, $callback ) = $wstore->insertWithTempTable( $this->db, $comment, $data );
list( $fields, $callback ) = $wstore->insertWithTempTable(
$this->db, $key, $comment, $data
);
} else {
$fields = $wstore->insert( $this->db, $key, $comment, $data );
}
if ( $writeStage <= MIGRATION_WRITE_BOTH ) {
$this->assertSame( $expect['text'], $fields[$key], "old field, stage=$writeStage" );
} else {
$this->assertArrayNotHasKey( $key, $fields, "old field, stage=$writeStage" );
}
if ( $writeStage >= MIGRATION_WRITE_BOTH && !$usesTemp ) {
$this->assertArrayHasKey( "{$key}_id", $fields, "new field, stage=$writeStage" );
} else {
$this->assertArrayNotHasKey( "{$key}_id", $fields, "new field, stage=$writeStage" );
}
$this->db->insert( $table, $extraFields + $fields, __METHOD__ );
$id = $this->db->insertId();
if ( $usesTemp ) {
$callback( $id );
}
for ( $readStage = $readRange[0]; $readStage <= $readRange[1]; $readStage++ ) {
$rstore = $this->makeStore( $readStage );
$fieldRow = $this->db->selectRow(
$table,
$rstore->getFields( $key ),
[ $pk => $id ],
__METHOD__
);
$queryInfo = $rstore->getJoin( $key );
$joinRow = $this->db->selectRow(
[ $table ] + $queryInfo['tables'],
$queryInfo['fields'],
[ $pk => $id ],
__METHOD__,
[],
$queryInfo['joins']
);
$this->assertComment(
$writeStage === MIGRATION_OLD || $readStage === MIGRATION_OLD ? $expectOld : $expect,
$rstore->getCommentLegacy( $this->db, $key, $fieldRow ),
"w=$writeStage, r=$readStage, from getFields()"
);
$this->assertComment(
$writeStage === MIGRATION_OLD || $readStage === MIGRATION_OLD ? $expectOld : $expect,
$rstore->getComment( $key, $joinRow ),
"w=$writeStage, r=$readStage, from getJoin()"
);
}
}
}
/**
* @dataProvider provideInsertRoundTrip
* @param string $table
* @param string $key
* @param string $pk
* @param string $extraFields
* @param string|Message $comment
* @param array|null $data
* @param array $expect
*/
public function testInsertRoundTrip_withKeyConstruction(
$table, $key, $pk, $extraFields, $comment, $data, $expect
) {
$expectOld = [
'text' => $expect['text'],
'message' => new RawMessage( '$1', [ $expect['text'] ] ),
'data' => null,
];
$stages = [
MIGRATION_OLD => [ MIGRATION_OLD, MIGRATION_WRITE_NEW ],
MIGRATION_WRITE_BOTH => [ MIGRATION_OLD, MIGRATION_NEW ],
MIGRATION_WRITE_NEW => [ MIGRATION_WRITE_BOTH, MIGRATION_NEW ],
MIGRATION_NEW => [ MIGRATION_WRITE_BOTH, MIGRATION_NEW ],
];
foreach ( $stages as $writeStage => $readRange ) {
if ( $key === 'ipb_reason' ) {
$extraFields['ipb_address'] = __CLASS__ . "#$writeStage";
}
$wstore = $this->makeStoreWithKey( $writeStage, $key );
$usesTemp = $key === 'rev_comment';
if ( $usesTemp ) {
list( $fields, $callback ) = $wstore->insertWithTempTable(
$this->db, $comment, $data
);
} else {
$fields = $wstore->insert( $this->db, $comment, $data );
}
@ -370,7 +500,7 @@ class CommentStoreTest extends MediaWikiLangTestCase {
}
for ( $readStage = $readRange[0]; $readStage <= $readRange[1]; $readStage++ ) {
$rstore = $this->makeStore( $readStage, $key );
$rstore = $this->makeStoreWithKey( $readStage, $key );
$fieldRow = $this->db->selectRow(
$table,
@ -521,23 +651,23 @@ class CommentStoreTest extends MediaWikiLangTestCase {
MediaWiki\suppressWarnings();
$reset = new ScopedCallback( 'MediaWiki\restoreWarnings' );
$store = $this->makeStore( MIGRATION_OLD, 'dummy' );
$res = $store->getComment( [ 'dummy' => 'comment' ] );
$store = $this->makeStore( MIGRATION_OLD );
$res = $store->getComment( 'dummy', [ 'dummy' => 'comment' ] );
$this->assertSame( '', $res->text );
$res = $store->getComment( [ 'dummy' => 'comment' ], true );
$res = $store->getComment( 'dummy', [ 'dummy' => 'comment' ], true );
$this->assertSame( 'comment', $res->text );
$store = $this->makeStore( MIGRATION_NEW, 'dummy' );
$store = $this->makeStore( MIGRATION_NEW );
try {
$store->getComment( [ 'dummy' => 'comment' ] );
$store->getComment( 'dummy', [ 'dummy' => 'comment' ] );
$this->fail( 'Expected exception not thrown' );
} catch ( InvalidArgumentException $ex ) {
$this->assertSame( '$row does not contain fields needed for comment dummy', $ex->getMessage() );
}
$res = $store->getComment( [ 'dummy' => 'comment' ], true );
$res = $store->getComment( 'dummy', [ 'dummy' => 'comment' ], true );
$this->assertSame( 'comment', $res->text );
try {
$store->getComment( [ 'dummy_id' => 1 ] );
$store->getComment( 'dummy', [ 'dummy_id' => 1 ] );
$this->fail( 'Expected exception not thrown' );
} catch ( InvalidArgumentException $ex ) {
$this->assertSame(
@ -547,19 +677,19 @@ class CommentStoreTest extends MediaWikiLangTestCase {
);
}
$store = $this->makeStore( MIGRATION_NEW, 'rev_comment' );
$store = $this->makeStore( MIGRATION_NEW );
try {
$store->getComment( [ 'rev_comment' => 'comment' ] );
$store->getComment( 'rev_comment', [ 'rev_comment' => 'comment' ] );
$this->fail( 'Expected exception not thrown' );
} catch ( InvalidArgumentException $ex ) {
$this->assertSame(
'$row does not contain fields needed for comment rev_comment', $ex->getMessage()
);
}
$res = $store->getComment( [ 'rev_comment' => 'comment' ], true );
$res = $store->getComment( 'rev_comment', [ 'rev_comment' => 'comment' ], true );
$this->assertSame( 'comment', $res->text );
try {
$store->getComment( [ 'rev_comment_pk' => 1 ] );
$store->getComment( 'rev_comment', [ 'rev_comment_pk' => 1 ] );
$this->fail( 'Expected exception not thrown' );
} catch ( InvalidArgumentException $ex ) {
$this->assertSame(
@ -586,8 +716,8 @@ class CommentStoreTest extends MediaWikiLangTestCase {
* @expectedExceptionMessage Must use insertWithTempTable() for rev_comment
*/
public function testInsertWrong( $stage ) {
$store = $this->makeStore( $stage, 'rev_comment' );
$store->insert( $this->db, 'foo' );
$store = $this->makeStore( $stage );
$store->insert( $this->db, 'rev_comment', 'foo' );
}
/**
@ -597,8 +727,8 @@ class CommentStoreTest extends MediaWikiLangTestCase {
* @expectedExceptionMessage Must use insert() for ipb_reason
*/
public function testInsertWithTempTableWrong( $stage ) {
$store = $this->makeStore( $stage, 'ipb_reason' );
$store->insertWithTempTable( $this->db, 'foo' );
$store = $this->makeStore( $stage );
$store->insertWithTempTable( $this->db, 'ipb_reason', 'foo' );
}
/**
@ -610,8 +740,8 @@ class CommentStoreTest extends MediaWikiLangTestCase {
$wrap->formerTempTables += [ 'ipb_reason' => '1.30' ];
$this->hideDeprecated( 'CommentStore::insertWithTempTable for ipb_reason' );
$store = $this->makeStore( $stage, 'ipb_reason' );
list( $fields, $callback ) = $store->insertWithTempTable( $this->db, 'foo' );
$store = $this->makeStore( $stage );
list( $fields, $callback ) = $store->insertWithTempTable( $this->db, 'ipb_reason', 'foo' );
$this->assertTrue( is_callable( $callback ) );
}
@ -620,8 +750,8 @@ class CommentStoreTest extends MediaWikiLangTestCase {
$truncated1 = str_repeat( '💣', 63 ) . '...';
$truncated2 = str_repeat( '💣', CommentStore::COMMENT_CHARACTER_LIMIT - 3 ) . '...';
$store = $this->makeStore( MIGRATION_WRITE_BOTH, 'ipb_reason' );
$fields = $store->insert( $this->db, $comment );
$store = $this->makeStore( MIGRATION_WRITE_BOTH );
$fields = $store->insert( $this->db, 'ipb_reason', $comment );
$this->assertSame( $truncated1, $fields['ipb_reason'] );
$stored = $this->db->selectField(
'comment', 'comment_text', [ 'comment_id' => $fields['ipb_reason_id'] ], __METHOD__
@ -634,13 +764,17 @@ class CommentStoreTest extends MediaWikiLangTestCase {
* @expectedExceptionMessage Comment data is too long (65611 bytes, maximum is 65535)
*/
public function testInsertTooMuchData() {
$store = $this->makeStore( MIGRATION_WRITE_BOTH, 'ipb_reason' );
$store->insert( $this->db, 'foo', [
$store = $this->makeStore( MIGRATION_WRITE_BOTH );
$store->insert( $this->db, 'ipb_reason', 'foo', [
'long' => str_repeat( '💣', 16400 )
] );
}
public function testConstructor() {
public function testGetStore() {
$this->assertInstanceOf( CommentStore::class, CommentStore::getStore() );
}
public function testNewKey() {
$this->assertInstanceOf( CommentStore::class, CommentStore::newKey( 'dummy' ) );
}

View file

@ -344,6 +344,7 @@ class MediaWikiServicesTest extends MediaWikiTestCase {
'RevisionStore' => [ 'RevisionStore', RevisionStore::class ],
'RevisionLookup' => [ 'RevisionLookup', RevisionLookup::class ],
'HttpRequestFactory' => [ 'HttpRequestFactory', HttpRequestFactory::class ],
'CommentStore' => [ 'CommentStore', CommentStore::class ],
];
}

View file

@ -114,6 +114,9 @@ class PageArchiveTest extends MediaWikiTestCase {
* @covers PageArchive::listRevisions
*/
public function testListRevisions() {
$this->setMwGlobals( 'wgCommentTableSchemaMigrationStage', MIGRATION_OLD );
$this->overrideMwServices();
$revisions = $this->archivedPage->listRevisions();
$this->assertEquals( 2, $revisions->numRows() );

View file

@ -938,6 +938,7 @@ class RevisionTest extends MediaWikiTestCase {
$this->hideDeprecated( 'Revision::selectFields' );
$this->setMwGlobals( 'wgContentHandlerUseDB', $contentHandlerUseDB );
$this->setMwGlobals( 'wgCommentTableSchemaMigrationStage', MIGRATION_OLD );
$this->overrideMwServices();
$this->assertEquals( $expected, Revision::selectFields() );
}
@ -997,6 +998,7 @@ class RevisionTest extends MediaWikiTestCase {
$this->hideDeprecated( 'Revision::selectArchiveFields' );
$this->setMwGlobals( 'wgContentHandlerUseDB', $contentHandlerUseDB );
$this->setMwGlobals( 'wgCommentTableSchemaMigrationStage', MIGRATION_OLD );
$this->overrideMwServices();
$this->assertEquals( $expected, Revision::selectArchiveFields() );
}

View file

@ -224,9 +224,10 @@ class RevisionStoreTest extends MediaWikiTestCase {
* @covers \MediaWiki\Storage\RevisionStore::getQueryInfo
*/
public function testGetQueryInfo( $contentHandlerUseDb, $options, $expected ) {
$this->setMwGlobals( 'wgCommentTableSchemaMigrationStage', MIGRATION_OLD );
$this->overrideMwServices();
$store = $this->getRevisionStore();
$store->setContentHandlerUseDB( $contentHandlerUseDb );
$this->setMwGlobals( 'wgCommentTableSchemaMigrationStage', MIGRATION_OLD );
$this->assertEquals( $expected, $store->getQueryInfo( $options ) );
}
@ -254,9 +255,10 @@ class RevisionStoreTest extends MediaWikiTestCase {
* @covers \MediaWiki\Storage\RevisionStore::getArchiveQueryInfo
*/
public function testGetArchiveQueryInfo_contentHandlerDb() {
$this->setMwGlobals( 'wgCommentTableSchemaMigrationStage', MIGRATION_OLD );
$this->overrideMwServices();
$store = $this->getRevisionStore();
$store->setContentHandlerUseDB( true );
$this->setMwGlobals( 'wgCommentTableSchemaMigrationStage', MIGRATION_OLD );
$this->assertEquals(
[
'tables' => [
@ -282,9 +284,10 @@ class RevisionStoreTest extends MediaWikiTestCase {
* @covers \MediaWiki\Storage\RevisionStore::getArchiveQueryInfo
*/
public function testGetArchiveQueryInfo_noContentHandlerDb() {
$this->setMwGlobals( 'wgCommentTableSchemaMigrationStage', MIGRATION_OLD );
$this->overrideMwServices();
$store = $this->getRevisionStore();
$store->setContentHandlerUseDB( false );
$this->setMwGlobals( 'wgCommentTableSchemaMigrationStage', MIGRATION_OLD );
$this->assertEquals(
[
'tables' => [

View file

@ -1084,6 +1084,8 @@ more stuff
*/
public function testCommentMigrationOnDeletion( $writeStage, $readStage ) {
$this->setMwGlobals( 'wgCommentTableSchemaMigrationStage', $writeStage );
$this->overrideMwServices();
$dbr = wfGetDB( DB_REPLICA );
$page = $this->createPage(
@ -1102,6 +1104,7 @@ more stuff
}
$this->setMwGlobals( 'wgCommentTableSchemaMigrationStage', $readStage );
$this->overrideMwServices();
$page->doDeleteArticle( "testing deletion" );

View file

@ -1,15 +1,32 @@
<?php
use Wikimedia\ScopedCallback;
use Wikimedia\TestingAccessWrapper;
/**
* @covers WatchedItemQueryService
*/
class WatchedItemQueryServiceUnitTest extends PHPUnit_Framework_TestCase {
class WatchedItemQueryServiceUnitTest extends MediaWikiTestCase {
use MediaWikiCoversValidator;
private function overrideCommentStore() {
$mockStore = $this->getMockBuilder( CommentStore::class )
->disableOriginalConstructor()
->getMock();
$mockStore->expects( $this->any() )
->method( 'getFields' )
->willReturn( [ 'commentstore' => 'fields' ] );
$mockStore->expects( $this->any() )
->method( 'getJoin' )
->willReturn( [
'tables' => [ 'commentstore' => 'table' ],
'fields' => [ 'commentstore' => 'field' ],
'joins' => [ 'commentstore' => 'join' ],
] );
$this->setService( 'CommentStore', $mockStore );
}
/**
* @return PHPUnit_Framework_MockObject_MockObject|Database
*/
@ -477,58 +494,11 @@ class WatchedItemQueryServiceUnitTest extends PHPUnit_Framework_TestCase {
[
[ 'includeFields' => [ WatchedItemQueryService::INCLUDE_COMMENT ] ],
null,
[],
[
'rc_comment_text' => 'rc_comment',
'rc_comment_data' => 'NULL',
'rc_comment_cid' => 'NULL',
],
[ 'commentstore' => 'table' ],
[ 'commentstore' => 'field' ],
[],
[],
[],
[ 'wgCommentTableSchemaMigrationStage' => MIGRATION_OLD ],
],
[
[ 'includeFields' => [ WatchedItemQueryService::INCLUDE_COMMENT ] ],
null,
[ 'comment_rc_comment' => 'comment' ],
[
'rc_comment_text' => 'COALESCE( comment_rc_comment.comment_text, rc_comment )',
'rc_comment_data' => 'comment_rc_comment.comment_data',
'rc_comment_cid' => 'comment_rc_comment.comment_id',
],
[],
[],
[ 'comment_rc_comment' => [ 'LEFT JOIN', 'comment_rc_comment.comment_id = rc_comment_id' ] ],
[ 'wgCommentTableSchemaMigrationStage' => MIGRATION_WRITE_BOTH ],
],
[
[ 'includeFields' => [ WatchedItemQueryService::INCLUDE_COMMENT ] ],
null,
[ 'comment_rc_comment' => 'comment' ],
[
'rc_comment_text' => 'COALESCE( comment_rc_comment.comment_text, rc_comment )',
'rc_comment_data' => 'comment_rc_comment.comment_data',
'rc_comment_cid' => 'comment_rc_comment.comment_id',
],
[],
[],
[ 'comment_rc_comment' => [ 'LEFT JOIN', 'comment_rc_comment.comment_id = rc_comment_id' ] ],
[ 'wgCommentTableSchemaMigrationStage' => MIGRATION_WRITE_NEW ],
],
[
[ 'includeFields' => [ WatchedItemQueryService::INCLUDE_COMMENT ] ],
null,
[ 'comment_rc_comment' => 'comment' ],
[
'rc_comment_text' => 'comment_rc_comment.comment_text',
'rc_comment_data' => 'comment_rc_comment.comment_data',
'rc_comment_cid' => 'comment_rc_comment.comment_id',
],
[],
[],
[ 'comment_rc_comment' => [ 'JOIN', 'comment_rc_comment.comment_id = rc_comment_id' ] ],
[ 'wgCommentTableSchemaMigrationStage' => MIGRATION_NEW ],
[ 'commentstore' => 'join' ],
],
[
[ 'includeFields' => [ WatchedItemQueryService::INCLUDE_PATROL_INFO ] ],
@ -836,22 +806,9 @@ class WatchedItemQueryServiceUnitTest extends PHPUnit_Framework_TestCase {
array $expectedExtraFields,
array $expectedExtraConds,
array $expectedDbOptions,
array $expectedExtraJoinConds,
array $globals = []
array $expectedExtraJoinConds
) {
// Sigh. This test class doesn't extend MediaWikiTestCase, so we have to reinvent setMwGlobals().
if ( $globals ) {
$resetGlobals = [];
foreach ( $globals as $k => $v ) {
$resetGlobals[$k] = $GLOBALS[$k];
$GLOBALS[$k] = $v;
}
$reset = new ScopedCallback( function () use ( $resetGlobals ) {
foreach ( $resetGlobals as $k => $v ) {
$GLOBALS[$k] = $v;
}
} );
}
$this->overrideCommentStore();
$expectedTables = array_merge( [ 'recentchanges', 'watchlist', 'page' ], $expectedExtraTables );
$expectedFields = array_merge(