diff options
author | jenkins-bot <jenkins-bot@gerrit.wikimedia.org> | 2022-01-10 19:17:04 +0000 |
---|---|---|
committer | Gerrit Code Review <gerrit@wikimedia.org> | 2022-01-10 19:17:04 +0000 |
commit | 7623cae28c8637b48d798133720362ba8ed79253 (patch) | |
tree | 4a123f61119800dafcf0f2979670f2de0b07b4e0 | |
parent | fb80b943b67a17a85111692fa4ac675f148f05e6 (diff) | |
parent | 87d8ccbd3e5280582a1bd60771b821ee5bbc95a7 (diff) |
Merge "Move the link updates from moveUnsafe() to LinksUpdate"
-rw-r--r-- | includes/MovePage.php | 49 | ||||
-rw-r--r-- | includes/Storage/DerivedPageDataUpdater.php | 5 | ||||
-rw-r--r-- | includes/deferred/LinksUpdate.php | 15 | ||||
-rw-r--r-- | includes/deferred/LinksUpdate/CategoryLinksTable.php | 50 | ||||
-rw-r--r-- | includes/deferred/LinksUpdate/GenericPageLinksTable.php | 4 | ||||
-rw-r--r-- | includes/deferred/LinksUpdate/ImageLinksTable.php | 4 | ||||
-rw-r--r-- | includes/deferred/LinksUpdate/LinksTable.php | 61 | ||||
-rw-r--r-- | includes/deferred/LinksUpdate/LinksTableGroup.php | 19 | ||||
-rw-r--r-- | tests/phpunit/includes/deferred/LinksUpdateTest.php | 122 |
9 files changed, 253 insertions, 76 deletions
diff --git a/includes/MovePage.php b/includes/MovePage.php index 1e2804b07792..e020aaf33b7f 100644 --- a/includes/MovePage.php +++ b/includes/MovePage.php @@ -693,35 +693,6 @@ class MovePage { $nullRevision = $moveAttemptResult; } - // Refresh the sortkey for this row. Be careful to avoid resetting - // cl_timestamp, which may disturb time-based lists on some sites. - // @todo This block should be killed, it's duplicating code - // from LinksUpdate::getCategoryInsertions() and friends. - $prefixes = $dbw->select( - 'categorylinks', - [ 'cl_sortkey_prefix', 'cl_to' ], - [ 'cl_from' => $pageid ], - __METHOD__ - ); - $type = $this->nsInfo->getCategoryLinkType( $this->newTitle->getNamespace() ); - $collation = $this->collationFactory->getCategoryCollation(); - foreach ( $prefixes as $prefixRow ) { - $prefix = $prefixRow->cl_sortkey_prefix; - $catTo = $prefixRow->cl_to; - $dbw->update( 'categorylinks', - [ - 'cl_sortkey' => $collation->getSortKey( - $this->newTitle->getCategorySortkey( $prefix ) ), - 'cl_collation' => $this->options->get( 'CategoryCollation' ), - 'cl_type' => $type, - 'cl_timestamp=cl_timestamp' ], - [ - 'cl_from' => $pageid, - 'cl_to' => $catTo ], - __METHOD__ - ); - } - $redirid = $this->oldTitle->getArticleID(); if ( $protected ) { @@ -781,25 +752,6 @@ class MovePage { $logEntry->publish( $logId ); } - // Update *_from_namespace fields as needed - if ( $this->oldTitle->getNamespace() != $this->newTitle->getNamespace() ) { - $dbw->update( 'pagelinks', - [ 'pl_from_namespace' => $this->newTitle->getNamespace() ], - [ 'pl_from' => $pageid ], - __METHOD__ - ); - $dbw->update( 'templatelinks', - [ 'tl_from_namespace' => $this->newTitle->getNamespace() ], - [ 'tl_from' => $pageid ], - __METHOD__ - ); - $dbw->update( 'imagelinks', - [ 'il_from_namespace' => $this->newTitle->getNamespace() ], - [ 'il_from' => $pageid ], - __METHOD__ - ); - } - # Update watchlists $oldtitle = $this->oldTitle->getDBkey(); $newtitle = $this->newTitle->getDBkey(); @@ -1028,6 +980,7 @@ class MovePage { $options = [ 'changed' => false, 'moved' => true, + 'oldtitle' => $this->oldTitle, 'oldcountable' => $oldcountable, 'causeAction' => 'edit-page', 'causeAgent' => $user->getName(), diff --git a/includes/Storage/DerivedPageDataUpdater.php b/includes/Storage/DerivedPageDataUpdater.php index 1ff1fee40fc7..e6998a516087 100644 --- a/includes/Storage/DerivedPageDataUpdater.php +++ b/includes/Storage/DerivedPageDataUpdater.php @@ -179,6 +179,7 @@ class DerivedPageDataUpdater implements IDBAccessObject, LoggerAwareInterface, P 'newrev' => false, 'created' => false, 'moved' => false, + 'oldtitle' => null, 'restored' => false, 'oldrevision' => null, 'oldcountable' => null, @@ -1135,6 +1136,7 @@ class DerivedPageDataUpdater implements IDBAccessObject, LoggerAwareInterface, P * - changed: bool, whether the revision changed the content (default true) * - created: bool, whether the revision created the page (default false) * - moved: bool, whether the page was moved (default false) + * - oldtitle: PageIdentity, if the page was moved this is the source title (default null) * - restored: bool, whether the page was undeleted (default false) * - oldrevision: RevisionRecord object for the pre-update revision (default null) * - triggeringUser: The user triggering the update (UserIdentity, defaults to the @@ -1424,6 +1426,9 @@ class DerivedPageDataUpdater implements IDBAccessObject, LoggerAwareInterface, P $parserOutput, $recursive ); + if ( $this->options['moved'] ) { + $linksUpdate->setMoveDetails( $this->options['oldtitle'] ); + } $allUpdates[] = $linksUpdate; // NOTE: Run updates for all slots, not just the modified slots! Otherwise, diff --git a/includes/deferred/LinksUpdate.php b/includes/deferred/LinksUpdate.php index 0abd53b681ee..6f87e3a48a86 100644 --- a/includes/deferred/LinksUpdate.php +++ b/includes/deferred/LinksUpdate.php @@ -30,6 +30,7 @@ use MediaWiki\HookContainer\ProtectedHookAccessorTrait; use MediaWiki\Logger\LoggerFactory; use MediaWiki\MediaWikiServices; use MediaWiki\Page\PageIdentity; +use MediaWiki\Page\PageReference; use MediaWiki\Page\PageReferenceValue; use MediaWiki\Revision\RevisionRecord; use MediaWiki\User\UserIdentity; @@ -167,6 +168,16 @@ class LinksUpdate extends DataUpdate { } /** + * Notify LinksUpdate that a move has just been completed and set the + * original title + * + * @param PageReference $oldPage + */ + public function setMoveDetails( PageReference $oldPage ) { + $this->tableFactory->setMoveDetails( $oldPage ); + } + + /** * Update link tables with outgoing links from an updated article * * @note this is managed by DeferredUpdates::execute(). Do not run this in a transaction. @@ -197,8 +208,8 @@ class LinksUpdate extends DataUpdate { // Calling getAll() here has the side-effect of calling // LinksUpdateBatch::setParserOutput() on all subclasses, allowing // those methods to also do pre-lock operations. - foreach ( $this->tableFactory->getAll() as $batch ) { - $batch->beforeLock(); + foreach ( $this->tableFactory->getAll() as $table ) { + $table->beforeLock(); } if ( $this->ticket ) { diff --git a/includes/deferred/LinksUpdate/CategoryLinksTable.php b/includes/deferred/LinksUpdate/CategoryLinksTable.php index 505623a132b5..a40ceff3a7da 100644 --- a/includes/deferred/LinksUpdate/CategoryLinksTable.php +++ b/includes/deferred/LinksUpdate/CategoryLinksTable.php @@ -35,6 +35,12 @@ class CategoryLinksTable extends TitleLinksTable { */ private $existingLinks; + /** + * @var array Associative array of saved timestamps, if there is a force + * refresh due to a page move + */ + private $savedTimestamps = null; + /** @var \ILanguageConverter */ private $languageConverter; @@ -129,7 +135,11 @@ class CategoryLinksTable extends TitleLinksTable { } protected function getExistingFields() { - return [ 'cl_to', 'cl_sortkey_prefix' ]; + $fields = [ 'cl_to', 'cl_sortkey_prefix' ]; + if ( $this->needForcedLinkRefresh() ) { + $fields[] = 'cl_timestamp'; + } + return $fields; } /** @@ -145,6 +155,21 @@ class CategoryLinksTable extends TitleLinksTable { } /** + * Get the existing links from the database + */ + private function fetchExistingLinks() { + $this->existingLinks = []; + $this->savedTimestamps = []; + $force = $this->needForcedLinkRefresh(); + foreach ( $this->fetchExistingRows() as $row ) { + $this->existingLinks[$row->cl_to] = $row->cl_sortkey_prefix; + if ( $force ) { + $this->savedTimestamps[$row->cl_to] = $row->cl_timestamp; + } + } + } + + /** * Get the existing links as an associative array, with the category name * in the key and the sort key prefix in the value. * @@ -152,14 +177,18 @@ class CategoryLinksTable extends TitleLinksTable { */ private function getExistingLinks() { if ( $this->existingLinks === null ) { - $this->existingLinks = []; - foreach ( $this->fetchExistingRows() as $row ) { - $this->existingLinks[$row->cl_to] = $row->cl_sortkey_prefix; - } + $this->fetchExistingLinks(); } return $this->existingLinks; } + private function getSavedTimestamps() { + if ( $this->savedTimestamps === null ) { + $this->fetchExistingLinks(); + } + return $this->savedTimestamps; + } + /** * @return \Generator */ @@ -184,11 +213,15 @@ class CategoryLinksTable extends TitleLinksTable { protected function insertLink( $linkId ) { [ $name, $prefix ] = $linkId; $sortKey = $this->newLinks[$name][1]; + $savedTimestamps = $this->getSavedTimestamps(); + + // Preserve cl_timestamp in the case of a forced refresh + $timestamp = $this->getDB()->timestamp( $savedTimestamps[$name] ?? 0 ); $this->insertRow( [ 'cl_to' => $name, 'cl_sortkey' => $sortKey, - 'cl_timestamp' => $this->getDB()->timestamp(), + 'cl_timestamp' => $timestamp, 'cl_sortkey_prefix' => $prefix, 'cl_collation' => $this->collationName, 'cl_type' => $this->categoryType, @@ -199,6 +232,11 @@ class CategoryLinksTable extends TitleLinksTable { $this->deleteRow( [ 'cl_to' => $linkId[0] ] ); } + protected function needForcedLinkRefresh() { + // cl_sortkey and possibly cl_type will change if it is a page move + return $this->isMove(); + } + protected function makePageReferenceValue( $linkId ): PageReferenceValue { return new PageReferenceValue( NS_CATEGORY, $linkId[0], WikiAwareEntity::LOCAL ); } diff --git a/includes/deferred/LinksUpdate/GenericPageLinksTable.php b/includes/deferred/LinksUpdate/GenericPageLinksTable.php index acf06e630ae0..a1bcd845218f 100644 --- a/includes/deferred/LinksUpdate/GenericPageLinksTable.php +++ b/includes/deferred/LinksUpdate/GenericPageLinksTable.php @@ -116,6 +116,10 @@ abstract class GenericPageLinksTable extends TitleLinksTable { ] ); } + protected function needForcedLinkRefresh() { + return $this->isCrossNamespaceMove(); + } + protected function makePageReferenceValue( $linkId ): PageReferenceValue { return new PageReferenceValue( $linkId[0], $linkId[1], WikiAwareEntity::LOCAL ); } diff --git a/includes/deferred/LinksUpdate/ImageLinksTable.php b/includes/deferred/LinksUpdate/ImageLinksTable.php index bc0adcdb6a13..8ecfb2f5a8b4 100644 --- a/includes/deferred/LinksUpdate/ImageLinksTable.php +++ b/includes/deferred/LinksUpdate/ImageLinksTable.php @@ -78,6 +78,10 @@ class ImageLinksTable extends TitleLinksTable { return \array_key_exists( $linkId, $this->newLinks ); } + protected function needExistingLinkRefresh() { + return $this->isCrossNamespaceMove(); + } + protected function insertLink( $linkId ) { $this->insertRow( [ 'il_from_namespace' => $this->getSourcePage()->getNamespace(), diff --git a/includes/deferred/LinksUpdate/LinksTable.php b/includes/deferred/LinksUpdate/LinksTable.php index bc00d07d5b6b..21a43b81098e 100644 --- a/includes/deferred/LinksUpdate/LinksTable.php +++ b/includes/deferred/LinksUpdate/LinksTable.php @@ -3,6 +3,7 @@ namespace MediaWiki\Deferred\LinksUpdate; use MediaWiki\Page\PageIdentity; +use MediaWiki\Page\PageReference; use MediaWiki\Revision\RevisionRecord; use ParserOutput; use Wikimedia\Rdbms\IDatabase; @@ -84,6 +85,9 @@ abstract class LinksTable { /** @var PageIdentity */ private $sourcePage; + /** @var PageReference|null */ + private $movedPage; + /** @var int */ private $batchSize; @@ -141,6 +145,16 @@ abstract class LinksTable { } /** + * Notify the object that the operation is a page move, and set the + * original title. + * + * @param PageReference $movedPage + */ + public function setMoveDetails( PageReference $movedPage ) { + $this->movedPage = $movedPage; + } + + /** * Subclasses should implement this to extract the data they need from the * ParserOutput. * @@ -228,6 +242,17 @@ abstract class LinksTable { abstract protected function deleteLink( $linkId ); /** + * Subclasses can override this to return true in order to force + * reinsertion of all the links due to some property of the link + * changing for reasons not represented by the link ID. + * + * @return bool + */ + protected function needForcedLinkRefresh() { + return false; + } + + /** * @stable to override * @return IDatabase */ @@ -262,6 +287,35 @@ abstract class LinksTable { } /** + * Determine whether the page was moved + * + * @return bool + */ + protected function isMove() { + return $this->movedPage !== null; + } + + /** + * Determine whether the page was moved to a different namespace. + * + * @return bool + */ + protected function isCrossNamespaceMove() { + return $this->movedPage !== null + && $this->sourcePage->getNamespace() !== $this->movedPage->getNamespace(); + } + + /** + * Assuming the page was moved, get the original page title before the move. + * This will throw an exception if the page wasn't moved. + * + * @return PageReference + */ + protected function getMovedPage(): PageReference { + return $this->movedPage; + } + + /** * Get the maximum number of rows to update in a batch. * * @return int @@ -315,19 +369,20 @@ abstract class LinksTable { } /** - * Execute the update + * Execute an edit/delete update */ final public function update() { $this->startUpdate(); + $force = $this->needForcedLinkRefresh(); foreach ( $this->getNewLinkIDs() as $link ) { - if ( !$this->isExisting( $link ) ) { + if ( $force || !$this->isExisting( $link ) ) { $this->insertLink( $link ); $this->insertedLinks[] = $link; } } foreach ( $this->getExistingLinkIDs() as $link ) { - if ( !$this->isInNewSet( $link ) ) { + if ( $force || !$this->isInNewSet( $link ) ) { $this->deleteLink( $link ); $this->deletedLinks[] = $link; } diff --git a/includes/deferred/LinksUpdate/LinksTableGroup.php b/includes/deferred/LinksUpdate/LinksTableGroup.php index fb8f91866c50..4fb7c005d30e 100644 --- a/includes/deferred/LinksUpdate/LinksTableGroup.php +++ b/includes/deferred/LinksUpdate/LinksTableGroup.php @@ -6,6 +6,7 @@ use MediaWiki\Collation\CollationFactory; use MediaWiki\Config\ServiceOptions; use MediaWiki\MediaWikiServices; use MediaWiki\Page\PageIdentity; +use MediaWiki\Page\PageReference; use MediaWiki\Revision\RevisionRecord; use ParserOutput; use Wikimedia\ObjectFactory\ObjectFactory; @@ -74,6 +75,9 @@ class LinksTableGroup { /** @var PageIdentity */ private $page; + /** @var PageReference|null */ + private $movedPage; + /** @var ParserOutput|null */ private $parserOutput; @@ -138,6 +142,18 @@ class LinksTableGroup { } /** + * Set the original title in the case of a page move. + * + * @param PageReference $oldPage + */ + public function setMoveDetails( PageReference $oldPage ) { + $this->movedPage = $oldPage; + foreach ( $this->tables as $table ) { + $table->setMoveDetails( $oldPage ); + } + } + + /** * Set the transaction ticket to be used in new and existing objects. * * @param mixed $ticket @@ -248,6 +264,9 @@ class LinksTableGroup { if ( $this->parserOutput ) { $table->setParserOutput( $this->parserOutput ); } + if ( $this->movedPage ) { + $table->setMoveDetails( $this->movedPage ); + } if ( $this->ticket ) { $table->setTransactionTicket( $this->ticket ); } diff --git a/tests/phpunit/includes/deferred/LinksUpdateTest.php b/tests/phpunit/includes/deferred/LinksUpdateTest.php index db3efd269ce4..111621e153aa 100644 --- a/tests/phpunit/includes/deferred/LinksUpdateTest.php +++ b/tests/phpunit/includes/deferred/LinksUpdateTest.php @@ -1,5 +1,6 @@ <?php +use MediaWiki\Page\PageIdentityValue; use PHPUnit\Framework\MockObject\MockObject; use Wikimedia\TestingAccessWrapper; @@ -104,8 +105,7 @@ class LinksUpdateTest extends MediaWikiLangTestCase { $t, $po, 'pagelinks', - 'pl_namespace, - pl_title', + [ 'pl_namespace', 'pl_title' ], 'pl_from = ' . self::$testingPageId, [ [ NS_MAIN, 'Bar' ], @@ -128,8 +128,7 @@ class LinksUpdateTest extends MediaWikiLangTestCase { $t, $po, 'pagelinks', - 'pl_namespace, - pl_title', + [ 'pl_namespace', 'pl_title' ], 'pl_from = ' . self::$testingPageId, [ [ NS_MAIN, 'Bar' ], @@ -146,6 +145,36 @@ class LinksUpdateTest extends MediaWikiLangTestCase { ], $update->getRemovedLinks() ); } + public function testUpdate_pagelinks_move() { + list( $t, $po ) = $this->makeTitleAndParserOutput( "Testing", self::$testingPageId ); + + $po->addLink( Title::newFromText( "Foo" ) ); + $this->assertLinksUpdate( + $t, + $po, + 'pagelinks', + [ 'pl_namespace', 'pl_title', 'pl_from_namespace' ], + 'pl_from = ' . self::$testingPageId, + [ + [ NS_MAIN, 'Foo', NS_MAIN ], + ] + ); + + list( $t, $po ) = $this->makeTitleAndParserOutput( "User:Testing", self::$testingPageId ); + $po->addLink( Title::newFromText( "Foo" ) ); + $this->assertMoveLinksUpdate( + $t, + new PageIdentityValue( 2, 0, "Foo", false ), + $po, + 'pagelinks', + [ 'pl_namespace', 'pl_title', 'pl_from_namespace' ], + 'pl_from = ' . self::$testingPageId, + [ + [ NS_MAIN, 'Foo', NS_USER ], + ] + ); + } + /** * @covers ParserOutput::addExternalLink * @covers LinksUpdate::getAddedExternalLinks @@ -162,7 +191,7 @@ class LinksUpdateTest extends MediaWikiLangTestCase { $t, $po, 'externallinks', - 'el_to, el_index', + [ 'el_to', 'el_index' ], 'el_from = ' . self::$testingPageId, [ [ 'http://testing.com/wiki/Bar', 'http://com.testing./wiki/Bar' ], @@ -183,7 +212,7 @@ class LinksUpdateTest extends MediaWikiLangTestCase { $t, $po, 'externallinks', - 'el_to, el_index', + [ 'el_to', 'el_index' ], 'el_from = ' . self::$testingPageId, [ [ 'http://testing.com/wiki/Bar', 'http://com.testing./wiki/Bar' ], @@ -215,7 +244,7 @@ class LinksUpdateTest extends MediaWikiLangTestCase { $t, $po, 'categorylinks', - 'cl_to, cl_sortkey', + [ 'cl_to', 'cl_sortkey' ], 'cl_from = ' . self::$testingPageId, [ [ 'Bar', "BAR\nTESTING" ], @@ -242,7 +271,7 @@ class LinksUpdateTest extends MediaWikiLangTestCase { $t, $po, 'categorylinks', - 'cl_to, cl_sortkey', + [ 'cl_to', 'cl_sortkey' ], 'cl_from = ' . self::$testingPageId, [ [ 'Bar', "BAR\nTESTING" ], @@ -356,6 +385,56 @@ class LinksUpdateTest extends MediaWikiLangTestCase { ); } + public function testUpdate_categorylinks_move() { + $this->setMwGlobals( 'wgCategoryCollation', 'uppercase' ); + + /** @var ParserOutput $po */ + list( $t, $po ) = $this->makeTitleAndParserOutput( "Old", self::$testingPageId ); + + $po->addCategory( "Foo", "FOO" ); + + $this->assertLinksUpdate( + $t, + $po, + 'categorylinks', + [ 'cl_to', 'cl_sortkey' ], + 'cl_from = ' . self::$testingPageId, + [ + [ 'Foo', "FOO\nOLD" ] + ] + ); + + /** @var ParserOutput $po */ + list( $t, $po ) = $this->makeTitleAndParserOutput( "New", self::$testingPageId ); + + $po->addCategory( "Foo", "FOO" ); + + // An update to cl_sortkey is not expected if there was no move + $this->assertLinksUpdate( + $t, + $po, + 'categorylinks', + [ 'cl_to', 'cl_sortkey' ], + 'cl_from = ' . self::$testingPageId, + [ + [ 'Foo', "FOO\nOLD" ] + ] + ); + + // With move notification, update to cl_sortkey is expected + $this->assertMoveLinksUpdate( + $t, + new PageIdentityValue( 2, 0, "new", false ), + $po, + 'categorylinks', + [ 'cl_to', 'cl_sortkey' ], + 'cl_from = ' . self::$testingPageId, + [ + [ 'Foo', "FOO\nNEW" ] + ] + ); + } + /** * @covers ParserOutput::addInterwikiLink */ @@ -373,7 +452,7 @@ class LinksUpdateTest extends MediaWikiLangTestCase { $t, $po, 'iwlinks', - 'iwl_prefix, iwl_title', + [ 'iwl_prefix', 'iwl_title' ], 'iwl_from = ' . self::$testingPageId, [ [ 'linksupdatetest', 'T1' ], @@ -391,7 +470,7 @@ class LinksUpdateTest extends MediaWikiLangTestCase { $t, $po, 'iwlinks', - 'iwl_prefix, iwl_title', + [ 'iwl_prefix', 'iwl_title' ], 'iwl_from = ' . self::$testingPageId, [ [ 'linksupdatetest', 'T2' ], @@ -418,8 +497,7 @@ class LinksUpdateTest extends MediaWikiLangTestCase { $t, $po, 'templatelinks', - 'tl_namespace, - tl_title', + [ 'tl_namespace', 'tl_title' ], 'tl_from = ' . self::$testingPageId, [ [ NS_TEMPLATE, 'T1' ], @@ -437,8 +515,7 @@ class LinksUpdateTest extends MediaWikiLangTestCase { $t, $po, 'templatelinks', - 'tl_namespace, - tl_title', + [ 'tl_namespace', 'tl_title' ], 'tl_from = ' . self::$testingPageId, [ [ NS_TEMPLATE, 'T2' ], @@ -501,7 +578,7 @@ class LinksUpdateTest extends MediaWikiLangTestCase { $t, $po, 'langlinks', - 'll_lang, ll_title', + [ 'll_lang', 'll_title' ], 'll_from = ' . self::$testingPageId, [ [ 'De', '1' ], @@ -518,7 +595,7 @@ class LinksUpdateTest extends MediaWikiLangTestCase { $t, $po, 'langlinks', - 'll_lang, ll_title', + [ 'll_lang', 'll_title' ], 'll_from = ' . self::$testingPageId, [ [ 'En', '2' ], @@ -598,8 +675,19 @@ class LinksUpdateTest extends MediaWikiLangTestCase { protected function assertLinksUpdate( Title $title, ParserOutput $parserOutput, $table, $fields, $condition, array $expectedRows ) { + return $this->assertMoveLinksUpdate( $title, null, $parserOutput, + $table, $fields, $condition, $expectedRows ); + } + + protected function assertMoveLinksUpdate( + Title $title, ?PageIdentityValue $oldTitle, ParserOutput $parserOutput, + $table, $fields, $condition, array $expectedRows + ) { $update = new LinksUpdate( $title, $parserOutput ); $update->setStrictTestMode(); + if ( $oldTitle ) { + $update->setMoveDetails( $oldTitle ); + } $update->doUpdate(); @@ -612,7 +700,7 @@ class LinksUpdateTest extends MediaWikiLangTestCase { ) { $this->assertSelect( [ 'recentchanges', 'comment' ], - 'rc_title, comment_text', + [ 'rc_title', 'comment_text' ], [ 'rc_type' => RC_CATEGORIZE, 'rc_namespace' => NS_CATEGORY, |