From 6c81cda26e713e51384e9a4556b6d78ea820263c Mon Sep 17 00:00:00 2001 From: Amir Sarabadani Date: Mon, 31 Oct 2022 11:28:37 +0100 Subject: [PATCH] [SECURITY] Use rev_page_timestamp in SpecialMobileHistory Like the core counterpart to avoid really slow queries. Also cleaning up and modernize all the db query stack. Using SelectQueryBuilder, simplify, use buildComparison, etc. Bug: T320987 Change-Id: I8eb91a0f490ef96a49d3aa8d6844d74a0ea06e04 --- extension.json | 1 + includes/specials/SpecialMobileHistory.php | 58 ++++++++-------------- 2 files changed, 23 insertions(+), 36 deletions(-) diff --git a/extension.json b/extension.json index 8db0a885a..33cf3094c 100644 --- a/extension.json +++ b/extension.json @@ -31,6 +31,7 @@ "History": { "class": "SpecialMobileHistory", "services": [ + "DBLoadBalancer", "NamespaceInfo", "RevisionFactory" ] diff --git a/includes/specials/SpecialMobileHistory.php b/includes/specials/SpecialMobileHistory.php index 340f19262..8e0cdeade 100644 --- a/includes/specials/SpecialMobileHistory.php +++ b/includes/specials/SpecialMobileHistory.php @@ -3,7 +3,9 @@ use MediaWiki\MediaWikiServices; use MediaWiki\Revision\RevisionFactory; use MediaWiki\Revision\RevisionRecord; +use Wikimedia\Rdbms\ILoadBalancer; use Wikimedia\Rdbms\IResultWrapper; +use Wikimedia\Rdbms\SelectQueryBuilder; /** * Mobile formatted history of a page @@ -12,7 +14,6 @@ class SpecialMobileHistory extends MobileSpecialPageFeed { /** @var bool Whether the mobile special page has a desktop special page */ protected $hasDesktopVersion = true; protected const LIMIT = 50; - private const DB_REVISIONS_TABLE = 'revision'; /** @var string|null Timestamp to offset results from */ protected $offset; @@ -33,35 +34,18 @@ class SpecialMobileHistory extends MobileSpecialPageFeed { /** @var RevisionFactory */ private $revisionFactory; - /** - * @param NamespaceInfo $namespaceInfo - * @param RevisionFactory $revisionFactory - */ + /** @var ILoadBalancer */ + private $dbLoadBalancer; + public function __construct( - NamespaceInfo $namespaceInfo, RevisionFactory $revisionFactory + ILoadBalancer $dbLoadBalancer, NamespaceInfo $namespaceInfo, RevisionFactory $revisionFactory ) { $this->namespaceInfo = $namespaceInfo; $this->revisionFactory = $revisionFactory; + $this->dbLoadBalancer = $dbLoadBalancer; parent::__construct( $this->specialPageName ); } - /** - * Returns a list of query conditions that should be run against the revision table - * - * @return array List of conditions - */ - protected function getQueryConditions() { - $conds = []; - if ( $this->title ) { - $conds['rev_page'] = $this->title->getArticleID(); - } - if ( $this->offset ) { - $dbr = wfGetDB( DB_REPLICA, self::DB_REVISIONS_TABLE ); - $conds[] = 'rev_timestamp <= ' . $dbr->addQuotes( $this->offset ); - } - return $conds; - } - /** * Gets HTML to place in the header bar * @param Title $title The page to link to @@ -175,25 +159,27 @@ class SpecialMobileHistory extends MobileSpecialPageFeed { /** * Executes the database query and returns the result. - * @see getQueryConditions() * @return IResultWrapper */ protected function doQuery() { - $dbr = wfGetDB( DB_REPLICA, self::DB_REVISIONS_TABLE ); - $conds = $this->getQueryConditions(); - $options = [ - 'ORDER BY' => 'rev_timestamp DESC' - ]; - - $options['LIMIT'] = self::LIMIT + 1; - + $dbr = $this->dbLoadBalancer->getConnection( DB_REPLICA ); $revQuery = $this->revisionFactory->getQueryInfo(); + $queryBuilder = $dbr->newSelectQueryBuilder() + ->tables( $revQuery['tables'] ) + ->fields( $revQuery['fields'] ) + ->joinConds( $revQuery['joins'] ); - $res = $dbr->select( - $revQuery['tables'], $revQuery['fields'], $conds, __METHOD__, $options, $revQuery['joins'] - ); + if ( $this->title ) { + $queryBuilder->where( [ 'rev_page', $this->title->getArticleID() ] ); + } + if ( $this->offset ) { + $queryBuilder->where( $dbr->buildComparison('<=', [ 'rev_timestamp' => $this->offset ] ) ); + } + $queryBuilder->orderBy( 'rev_timestamp', SelectQueryBuilder::SORT_DESC ) + ->limit( self::LIMIT + 1 ) + ->useIndex( [ 'revision' => 'rev_page_timestamp' ] ); - return $res; + return $queryBuilder->caller( __METHOD__ )->fetchResultSet(); } /** -- 2.25.1