From: addshore Date: Wed, 24 Jan 2018 23:41:01 +0000 (-0800) Subject: Pass $key into CommentStore methods and use MediawikiServices X-Git-Tag: 1.31.0-rc.0~689^2 X-Git-Url: http://git.cyclocoop.org/%24self?a=commitdiff_plain;h=e5879da149afe183ce889ef6f4158086c9b4735f;p=lhc%2Fweb%2Fwiklou.git Pass $key into CommentStore methods and use MediawikiServices This allows CommentStore to be added to MediaWikiServices without the need of an aditional Factory. This change includes a compatability layer to allow the behaviour from 1.30 to continue to be used while deprecated. CommentStore::newKey has been deprecated. Keys are now passed into the public methods of CommentStore where needed. The following CommentStore methods have had their signatures changed to introduced a $key parameter, but when used in conjunction with CommentStore::newKey behaviour will remain unchanged: * CommentStore::getFields * CommentStore::getJoin * CommentStore::getComment * CommentStore::getCommentLegacy * CommentStore::insert * CommentStore::insertWithTemplate Change-Id: I3abb62a5cfb0dcd456da9f4eb35583476ae41cfb --- diff --git a/RELEASE-NOTES-1.31 b/RELEASE-NOTES-1.31 index b46d3d60ab..8261a39fe2 100644 --- a/RELEASE-NOTES-1.31 +++ b/RELEASE-NOTES-1.31 @@ -214,6 +214,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, diff --git a/includes/Block.php b/includes/Block.php index 0999ad2063..bdc6702f91 100644 --- a/includes/Block.php +++ b/includes/Block.php @@ -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 ); } /** diff --git a/includes/CommentStore.php b/includes/CommentStore.php index 0d679d37db..8447b2c797 100644 --- a/includes/CommentStore.php +++ b/includes/CommentStore.php @@ -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 + } + + if ( isset( self::$tempTables[$key] ) ) { + throw new InvalidArgumentException( "Must use insertWithTempTable() for $key" ); } - list( $fields ) = $this->insertInternal( $dbw, $comment, $data ); + 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 + } + + 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, $comment, $data ); + list( $fields, $callback ) = $this->insertInternal( $dbw, $key, $comment, $data ); if ( !$callback ) { $callback = function () { // Do nothing. diff --git a/includes/EditPage.php b/includes/EditPage.php index 6bf3c89213..6fbeed7b4d 100644 --- a/includes/EditPage.php +++ b/includes/EditPage.php @@ -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'], [ diff --git a/includes/FeedUtils.php b/includes/FeedUtils.php index 6108ca1d46..4dde52d0b4 100644 --- a/includes/FeedUtils.php +++ b/includes/FeedUtils.php @@ -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 ); } diff --git a/includes/MediaWikiServices.php b/includes/MediaWikiServices.php index c283793a91..9077666ddf 100644 --- a/includes/MediaWikiServices.php +++ b/includes/MediaWikiServices.php @@ -1,6 +1,7 @@ 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 diff --git a/includes/Revision.php b/includes/Revision.php index d5449b4ee4..eba563cfda 100644 --- a/includes/Revision.php +++ b/includes/Revision.php @@ -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'; diff --git a/includes/ServiceWiring.php b/includes/ServiceWiring.php index 847c1bb23c..dc397a2cc3 100644 --- a/includes/ServiceWiring.php +++ b/includes/ServiceWiring.php @@ -521,6 +521,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 diff --git a/includes/Storage/RevisionStore.php b/includes/Storage/RevisionStore.php index 79ecec691f..b358631aa0 100644 --- a/includes/Storage/RevisionStore.php +++ b/includes/Storage/RevisionStore.php @@ -360,7 +360,7 @@ class RevisionStore implements IDBAccessObject, RevisionFactory, RevisionLookup } list( $commentFields, $commentCallback ) = - CommentStore::newKey( 'rev_comment' )->insertWithTempTable( $dbw, $comment ); + CommentStore::getStore()->insertWithTempTable( $dbw, 'rev_comment', $comment ); $row += $commentFields; if ( $this->contentHandlerUseDB ) { @@ -1036,9 +1036,9 @@ class RevisionStore implements IDBAccessObject, RevisionFactory, RevisionLookup $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 ] ); @@ -1106,9 +1106,9 @@ class RevisionStore implements IDBAccessObject, RevisionFactory, RevisionLookup $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 ] ); @@ -1581,7 +1581,7 @@ class RevisionStore implements IDBAccessObject, RevisionFactory, RevisionLookup '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'] ); @@ -1638,7 +1638,7 @@ class RevisionStore implements IDBAccessObject, RevisionFactory, RevisionLookup * - 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' => [ diff --git a/includes/Title.php b/includes/Title.php index c4cf434126..0cdea35e54 100644 --- a/includes/Title.php +++ b/includes/Title.php @@ -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; diff --git a/includes/api/ApiQueryAllUsers.php b/includes/api/ApiQueryAllUsers.php index 65a4b32127..26844f3f26 100644 --- a/includes/api/ApiQueryAllUsers.php +++ b/includes/api/ApiQueryAllUsers.php @@ -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 ) { diff --git a/includes/api/ApiQueryBase.php b/includes/api/ApiQueryBase.php index e0ab53adb6..57a70bccfa 100644 --- a/includes/api/ApiQueryBase.php +++ b/includes/api/ApiQueryBase.php @@ -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'] ); diff --git a/includes/api/ApiQueryBlocks.php b/includes/api/ApiQueryBlocks.php index d02fefa76f..10695b30ca 100644 --- a/includes/api/ApiQueryBlocks.php +++ b/includes/api/ApiQueryBlocks.php @@ -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 ); diff --git a/includes/api/ApiQueryDeletedrevs.php b/includes/api/ApiQueryDeletedrevs.php index 5c1f6ba952..6e6757ecd1 100644 --- a/includes/api/ApiQueryDeletedrevs.php +++ b/includes/api/ApiQueryDeletedrevs.php @@ -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; } diff --git a/includes/api/ApiQueryFilearchive.php b/includes/api/ApiQueryFilearchive.php index d401511059..ebffb151c8 100644 --- a/includes/api/ApiQueryFilearchive.php +++ b/includes/api/ApiQueryFilearchive.php @@ -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 ); diff --git a/includes/api/ApiQueryLogEvents.php b/includes/api/ApiQueryLogEvents.php index 9d247940d2..f3453001c4 100644 --- a/includes/api/ApiQueryLogEvents.php +++ b/includes/api/ApiQueryLogEvents.php @@ -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; } diff --git a/includes/api/ApiQueryProtectedTitles.php b/includes/api/ApiQueryProtectedTitles.php index 843e209ec0..f5266850bd 100644 --- a/includes/api/ApiQueryProtectedTitles.php +++ b/includes/api/ApiQueryProtectedTitles.php @@ -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 ); } diff --git a/includes/api/ApiQueryRecentChanges.php b/includes/api/ApiQueryRecentChanges.php index 517cf1f860..e289e42d9c 100644 --- a/includes/api/ApiQueryRecentChanges.php +++ b/includes/api/ApiQueryRecentChanges.php @@ -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; } diff --git a/includes/api/ApiQueryUserContributions.php b/includes/api/ApiQueryUserContributions.php index 99a582ed4c..1705c57361 100644 --- a/includes/api/ApiQueryUserContributions.php +++ b/includes/api/ApiQueryUserContributions.php @@ -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; } diff --git a/includes/api/ApiQueryUsers.php b/includes/api/ApiQueryUsers.php index 6de512b878..824c4d5223 100644 --- a/includes/api/ApiQueryUsers.php +++ b/includes/api/ApiQueryUsers.php @@ -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; } diff --git a/includes/api/ApiQueryWatchlist.php b/includes/api/ApiQueryWatchlist.php index f9ac44a2b5..69f1838786 100644 --- a/includes/api/ApiQueryWatchlist.php +++ b/includes/api/ApiQueryWatchlist.php @@ -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; } diff --git a/includes/changes/RecentChange.php b/includes/changes/RecentChange.php index a47186581a..678e39aa83 100644 --- a/includes/changes/RecentChange.php +++ b/includes/changes/RecentChange.php @@ -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; } diff --git a/includes/export/WikiExporter.php b/includes/export/WikiExporter.php index 6e2a5a4f0c..6ce55eaa4e 100644 --- a/includes/export/WikiExporter.php +++ b/includes/export/WikiExporter.php @@ -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( diff --git a/includes/export/XmlDumpWriter.php b/includes/export/XmlDumpWriter.php index c46eb61ca3..e1c12de1b9 100644 --- a/includes/export/XmlDumpWriter.php +++ b/includes/export/XmlDumpWriter.php @@ -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"; } diff --git a/includes/filerepo/file/ArchivedFile.php b/includes/filerepo/file/ArchivedFile.php index 7f48659ba3..6577ab6742 100644 --- a/includes/filerepo/file/ArchivedFile.php +++ b/includes/filerepo/file/ArchivedFile.php @@ -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; diff --git a/includes/filerepo/file/LocalFile.php b/includes/filerepo/file/LocalFile.php index 7be8f06246..bf1181f74c 100644 --- a/includes/filerepo/file/LocalFile.php +++ b/includes/filerepo/file/LocalFile.php @@ -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; diff --git a/includes/filerepo/file/OldLocalFile.php b/includes/filerepo/file/OldLocalFile.php index 69e6896f0e..d08d0aefad 100644 --- a/includes/filerepo/file/OldLocalFile.php +++ b/includes/filerepo/file/OldLocalFile.php @@ -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(), diff --git a/includes/import/WikiRevision.php b/includes/import/WikiRevision.php index edb0c9af1c..3513f8ce42 100644 --- a/includes/import/WikiRevision.php +++ b/includes/import/WikiRevision.php @@ -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; diff --git a/includes/logging/LogEntry.php b/includes/logging/LogEntry.php index bf35d78d25..16b3593dd2 100644 --- a/includes/logging/LogEntry.php +++ b/includes/logging/LogEntry.php @@ -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(); diff --git a/includes/logging/LogPage.php b/includes/logging/LogPage.php index 77d9aa21ba..c84352eb79 100644 --- a/includes/logging/LogPage.php +++ b/includes/logging/LogPage.php @@ -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(); diff --git a/includes/page/WikiPage.php b/includes/page/WikiPage.php index a7f53df8be..a7eed5a98b 100644 --- a/includes/page/WikiPage.php +++ b/includes/page/WikiPage.php @@ -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; diff --git a/includes/rcfeed/IRCColourfulRCFeedFormatter.php b/includes/rcfeed/IRCColourfulRCFeedFormatter.php index 531a3eb203..158ee5951f 100644 --- a/includes/rcfeed/IRCColourfulRCFeedFormatter.php +++ b/includes/rcfeed/IRCColourfulRCFeedFormatter.php @@ -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'] diff --git a/includes/revisiondelete/RevDelLogItem.php b/includes/revisiondelete/RevDelLogItem.php index 998c695f17..b8b0c5c466 100644 --- a/includes/revisiondelete/RevDelLogItem.php +++ b/includes/revisiondelete/RevDelLogItem.php @@ -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, ]; } diff --git a/includes/revisiondelete/RevDelLogList.php b/includes/revisiondelete/RevDelLogList.php index 728deb8e09..f4e4faffff 100644 --- a/includes/revisiondelete/RevDelLogList.php +++ b/includes/revisiondelete/RevDelLogList.php @@ -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'], diff --git a/includes/specials/SpecialNewpages.php b/includes/specials/SpecialNewpages.php index 1639386e3b..ea0f0ed598 100644 --- a/includes/specials/SpecialNewpages.php +++ b/includes/specials/SpecialNewpages.php @@ -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, diff --git a/includes/specials/pagers/BlockListPager.php b/includes/specials/pagers/BlockListPager.php index 924fd06cf0..fe7cac0dd1 100644 --- a/includes/specials/pagers/BlockListPager.php +++ b/includes/specials/pagers/BlockListPager.php @@ -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'], diff --git a/includes/specials/pagers/DeletedContribsPager.php b/includes/specials/pagers/DeletedContribsPager.php index 38a332e6a1..8a76efbb25 100644 --- a/includes/specials/pagers/DeletedContribsPager.php +++ b/includes/specials/pagers/DeletedContribsPager.php @@ -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, diff --git a/includes/specials/pagers/ImageListPager.php b/includes/specials/pagers/ImageListPager.php index d80946a544..ae19d59c87 100644 --- a/includes/specials/pagers/ImageListPager.php +++ b/includes/specials/pagers/ImageListPager.php @@ -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 ); diff --git a/includes/specials/pagers/NewPagesPager.php b/includes/specials/pagers/NewPagesPager.php index a87bbb7567..61b648d4f6 100644 --- a/includes/specials/pagers/NewPagesPager.php +++ b/includes/specials/pagers/NewPagesPager.php @@ -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']; diff --git a/includes/specials/pagers/ProtectedPagesPager.php b/includes/specials/pagers/ProtectedPagesPager.php index af04703195..c4ea5f858e 100644 --- a/includes/specials/pagers/ProtectedPagesPager.php +++ b/includes/specials/pagers/ProtectedPagesPager.php @@ -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'], diff --git a/includes/watcheditem/WatchedItemQueryService.php b/includes/watcheditem/WatchedItemQueryService.php index 3478b0894c..d546f0a4e8 100644 --- a/includes/watcheditem/WatchedItemQueryService.php +++ b/includes/watcheditem/WatchedItemQueryService.php @@ -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' ] ]; diff --git a/maintenance/orphans.php b/maintenance/orphans.php index a1cf166a7d..945df32560 100644 --- a/maintenance/orphans.php +++ b/maintenance/orphans.php @@ -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 ) . ')'; } diff --git a/maintenance/rebuildrecentchanges.php b/maintenance/rebuildrecentchanges.php index f26d8b3063..672bae86ce 100644 --- a/maintenance/rebuildrecentchanges.php +++ b/maintenance/rebuildrecentchanges.php @@ -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__ ); diff --git a/tests/phpunit/includes/CommentStoreTest.php b/tests/phpunit/includes/CommentStoreTest.php index 9369f30629..84e1f3288e 100644 --- a/tests/phpunit/includes/CommentStoreTest.php +++ b/tests/phpunit/includes/CommentStoreTest.php @@ -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' ) ); } diff --git a/tests/phpunit/includes/MediaWikiServicesTest.php b/tests/phpunit/includes/MediaWikiServicesTest.php index 859a40fa5a..2e93f36516 100644 --- a/tests/phpunit/includes/MediaWikiServicesTest.php +++ b/tests/phpunit/includes/MediaWikiServicesTest.php @@ -344,6 +344,7 @@ class MediaWikiServicesTest extends MediaWikiTestCase { 'RevisionStore' => [ 'RevisionStore', RevisionStore::class ], 'RevisionLookup' => [ 'RevisionLookup', RevisionLookup::class ], 'HttpRequestFactory' => [ 'HttpRequestFactory', HttpRequestFactory::class ], + 'CommentStore' => [ 'CommentStore', CommentStore::class ], ]; } diff --git a/tests/phpunit/includes/PageArchiveTest.php b/tests/phpunit/includes/PageArchiveTest.php index 15b26c23e6..6fbe053361 100644 --- a/tests/phpunit/includes/PageArchiveTest.php +++ b/tests/phpunit/includes/PageArchiveTest.php @@ -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() ); diff --git a/tests/phpunit/includes/RevisionTest.php b/tests/phpunit/includes/RevisionTest.php index 73d69a528c..4518e15ecf 100644 --- a/tests/phpunit/includes/RevisionTest.php +++ b/tests/phpunit/includes/RevisionTest.php @@ -934,6 +934,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() ); } @@ -993,6 +994,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() ); } diff --git a/tests/phpunit/includes/Storage/RevisionStoreTest.php b/tests/phpunit/includes/Storage/RevisionStoreTest.php index c9e99780e1..b6aed7f2c2 100644 --- a/tests/phpunit/includes/Storage/RevisionStoreTest.php +++ b/tests/phpunit/includes/Storage/RevisionStoreTest.php @@ -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' => [ diff --git a/tests/phpunit/includes/page/WikiPageDbTestBase.php b/tests/phpunit/includes/page/WikiPageDbTestBase.php index b7fe47e53d..6b680e56d6 100644 --- a/tests/phpunit/includes/page/WikiPageDbTestBase.php +++ b/tests/phpunit/includes/page/WikiPageDbTestBase.php @@ -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" ); diff --git a/tests/phpunit/includes/watcheditem/WatchedItemQueryServiceUnitTest.php b/tests/phpunit/includes/watcheditem/WatchedItemQueryServiceUnitTest.php index ef2486d152..cb0e376146 100644 --- a/tests/phpunit/includes/watcheditem/WatchedItemQueryServiceUnitTest.php +++ b/tests/phpunit/includes/watcheditem/WatchedItemQueryServiceUnitTest.php @@ -1,15 +1,32 @@ 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', - ], - [], - [], - [], - [ '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', - ], + [ 'commentstore' => 'table' ], + [ 'commentstore' => 'field' ], [], [], - [ '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(