Created
March 22, 2026 22:43
-
-
Save ciencia/88e6bb68f16b4982971ecaa7b28a8a8d to your computer and use it in GitHub Desktop.
core-PagePropsDisplayTitleCache-REL1_43.patch
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/includes/MediaWikiServices.php b/includes/MediaWikiServices.php | |
| index 2a040a7861a..8d857a9eec4 100644 | |
| --- a/includes/MediaWikiServices.php | |
| +++ b/includes/MediaWikiServices.php | |
| @@ -51,6 +51,7 @@ use MediaWiki\Cache\HTMLCacheUpdater; | |
| use MediaWiki\Cache\LinkBatchFactory; | |
| use MediaWiki\Cache\LinkCache; | |
| use MediaWiki\Cache\UserCache; | |
| +use MediaWiki\Cache\PagePropsDisplayTitleCache; | |
| use MediaWiki\Category\TrackingCategories; | |
| use MediaWiki\ChangeTags\ChangeTagsStore; | |
| use MediaWiki\Collation\CollationFactory; | |
| @@ -1521,6 +1522,13 @@ class MediaWikiServices extends ServiceContainer { | |
| return $this->getService( 'PageProps' ); | |
| } | |
| + /** | |
| + * @since 1.XX | |
| + */ | |
| + public function getPagePropsDisplayTitleCache(): PagePropsDisplayTitleCache { | |
| + return $this->getService( 'PagePropsDisplayTitleCache' ); | |
| + } | |
| + | |
| /** | |
| * @since 1.40 | |
| */ | |
| diff --git a/includes/ServiceWiring.php b/includes/ServiceWiring.php | |
| index af33de1f2c7..bdeca2c0799 100644 | |
| --- a/includes/ServiceWiring.php | |
| +++ b/includes/ServiceWiring.php | |
| @@ -69,6 +69,7 @@ use MediaWiki\Cache\GenderCache; | |
| use MediaWiki\Cache\HTMLCacheUpdater; | |
| use MediaWiki\Cache\LinkBatchFactory; | |
| use MediaWiki\Cache\LinkCache; | |
| +use MediaWiki\Cache\PagePropsDisplayTitleCache; | |
| use MediaWiki\Cache\UserCache; | |
| use MediaWiki\Category\TrackingCategories; | |
| use MediaWiki\ChangeTags\ChangeTagsStore; | |
| @@ -1104,7 +1105,8 @@ return [ | |
| $services->getGenderCache(), | |
| $services->getConnectionProvider(), | |
| $services->getLinksMigration(), | |
| - LoggerFactory::getInstance( 'LinkBatch' ) | |
| + LoggerFactory::getInstance( 'LinkBatch' ), | |
| + $services->getPagePropsDisplayTitleCache() | |
| ); | |
| }, | |
| @@ -1462,6 +1464,14 @@ return [ | |
| ); | |
| }, | |
| + 'PagePropsDisplayTitleCache' => static function ( MediaWikiServices $services ): PagePropsDisplayTitleCache { | |
| + // Database layer may be disabled, so processing without database connection | |
| + $dbLoadBalancer = $services->isServiceDisabled( 'DBLoadBalancer' ) | |
| + ? null | |
| + : $services->getDBLoadBalancerFactory(); | |
| + return new PagePropsDisplayTitleCache( $dbLoadBalancer ); | |
| + }, | |
| + | |
| 'PageRestHelperFactory' => static function ( MediaWikiServices $services ): PageRestHelperFactory { | |
| return new PageRestHelperFactory( | |
| new ServiceOptions( PageRestHelperFactory::CONSTRUCTOR_OPTIONS, $services->getMainConfig() ), | |
| diff --git a/includes/cache/LinkBatch.php b/includes/cache/LinkBatch.php | |
| index 990c4c187b5..b6f02d0b4ae 100644 | |
| --- a/includes/cache/LinkBatch.php | |
| +++ b/includes/cache/LinkBatch.php | |
| @@ -92,6 +92,9 @@ class LinkBatch { | |
| /** @var LoggerInterface */ | |
| private $logger; | |
| + /** @var PagePropsDisplayTitleCache */ | |
| + private $pagePropsDisplayTitleCache; | |
| + | |
| /** | |
| * @see \MediaWiki\Cache\LinkBatchFactory | |
| * | |
| @@ -113,7 +116,8 @@ class LinkBatch { | |
| GenderCache $genderCache, | |
| IConnectionProvider $dbProvider, | |
| LinksMigration $linksMigration, | |
| - LoggerInterface $logger | |
| + LoggerInterface $logger, | |
| + PagePropsDisplayTitleCache $pagePropsDisplayTitleCache | |
| ) { | |
| $this->linkCache = $linkCache; | |
| $this->titleFormatter = $titleFormatter; | |
| @@ -122,6 +126,7 @@ class LinkBatch { | |
| $this->dbProvider = $dbProvider; | |
| $this->linksMigration = $linksMigration; | |
| $this->logger = $logger; | |
| + $this->pagePropsDisplayTitleCache = $pagePropsDisplayTitleCache; | |
| foreach ( $arr as $item ) { | |
| $this->addObj( $item ); | |
| @@ -241,6 +246,7 @@ class LinkBatch { | |
| protected function executeInto( $cache ) { | |
| $res = $this->doQuery(); | |
| $this->doGenderQuery(); | |
| + $this->doPagePropsDisplayTitleQuery( $res ); | |
| return $this->addResultToCache( $cache, $res ); | |
| } | |
| @@ -356,6 +362,22 @@ class LinkBatch { | |
| return true; | |
| } | |
| + /** | |
| + * Do (and cache) page properties for display title in this LinkBatch | |
| + * | |
| + * @param IResultWrapper $res | |
| + * @return bool Whether the query was successful | |
| + */ | |
| + public function doPagePropsDisplayTitleQuery( $res ) { | |
| + if ( $this->isEmpty() ) { | |
| + return false; | |
| + } | |
| + | |
| + $this->pagePropsDisplayTitleCache->doLinkBatch( $res ); | |
| + | |
| + return true; | |
| + } | |
| + | |
| /** | |
| * Construct a WHERE clause which will match all the given titles. | |
| * | |
| diff --git a/includes/cache/LinkBatchFactory.php b/includes/cache/LinkBatchFactory.php | |
| index 78f46bcfa99..6b10e13274e 100644 | |
| --- a/includes/cache/LinkBatchFactory.php | |
| +++ b/includes/cache/LinkBatchFactory.php | |
| @@ -68,6 +68,9 @@ class LinkBatchFactory { | |
| /** @var LoggerInterface */ | |
| private $logger; | |
| + /** @var PagePropsDisplayTitleCache */ | |
| + private $pagePropsDisplayTitleCache; | |
| + | |
| public function __construct( | |
| LinkCache $linkCache, | |
| TitleFormatter $titleFormatter, | |
| @@ -75,7 +78,8 @@ class LinkBatchFactory { | |
| GenderCache $genderCache, | |
| IConnectionProvider $dbProvider, | |
| LinksMigration $linksMigration, | |
| - LoggerInterface $logger | |
| + LoggerInterface $logger, | |
| + PagePropsDisplayTitleCache $pagePropsDisplayTitleCache | |
| ) { | |
| $this->linkCache = $linkCache; | |
| $this->titleFormatter = $titleFormatter; | |
| @@ -84,6 +88,7 @@ class LinkBatchFactory { | |
| $this->dbProvider = $dbProvider; | |
| $this->linksMigration = $linksMigration; | |
| $this->logger = $logger; | |
| + $this->pagePropsDisplayTitleCache = $pagePropsDisplayTitleCache; | |
| } | |
| /** | |
| @@ -100,7 +105,8 @@ class LinkBatchFactory { | |
| $this->genderCache, | |
| $this->dbProvider, | |
| $this->linksMigration, | |
| - $this->logger | |
| + $this->logger, | |
| + $this->pagePropsDisplayTitleCache | |
| ); | |
| } | |
| } | |
| diff --git a/includes/cache/PagePropsDisplayTitleCache.php b/includes/cache/PagePropsDisplayTitleCache.php | |
| new file mode 100644 | |
| index 00000000000..277b42e3e8a | |
| --- /dev/null | |
| +++ b/includes/cache/PagePropsDisplayTitleCache.php | |
| @@ -0,0 +1,131 @@ | |
| +<?php | |
| +/** | |
| + * This program is free software; you can redistribute it and/or modify | |
| + * it under the terms of the GNU General Public License as published by | |
| + * the Free Software Foundation; either version 2 of the License, or | |
| + * (at your option) any later version. | |
| + * | |
| + * This program is distributed in the hope that it will be useful, | |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| + * GNU General Public License for more details. | |
| + * | |
| + * You should have received a copy of the GNU General Public License along | |
| + * with this program; if not, write to the Free Software Foundation, Inc., | |
| + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |
| + * http://www.gnu.org/copyleft/gpl.html | |
| + * | |
| + * @file | |
| + * @author Ciencia Al Poder | |
| + */ | |
| + | |
| +namespace MediaWiki\Cache; | |
| + | |
| +use Wikimedia\Rdbms\IConnectionProvider; | |
| + | |
| +/** | |
| + * Look up page properties for display title | |
| + * | |
| + * @since 1.43 | |
| + * @ingroup Cache | |
| + */ | |
| +class PagePropsDisplayTitleCache { | |
| + /** | |
| + * Page properties to fetch | |
| + */ | |
| + public const PAGE_PROPERTIES = [ | |
| + 'displaylink', | |
| + 'displaytitle', | |
| + ]; | |
| + | |
| + /** @var array<int,array<string,string>> */ | |
| + protected $cache = []; | |
| + /** @var int */ | |
| + protected $misses = 0; | |
| + /** | |
| + * @internal Exposed for MediaWiki core unit tests. | |
| + * @var int | |
| + */ | |
| + protected $missLimit = 1000; | |
| + | |
| + private ?IConnectionProvider $dbProvider; | |
| + | |
| + public function __construct( | |
| + ?IConnectionProvider $dbProvider = null | |
| + ) { | |
| + $this->dbProvider = $dbProvider; | |
| + } | |
| + | |
| + /** | |
| + * Get display title properties for a page id | |
| + * | |
| + * @param int $pageId Page id | |
| + * @param string|null $caller Calling method for database profiling | |
| + * @return array<string,string> | |
| + */ | |
| + public function getProperties( $pageId, $caller = '' ) { | |
| + if ( !array_key_exists( $pageId, $this->cache ) ) { | |
| + if ( $this->misses < $this->missLimit ) { | |
| + $this->misses++; | |
| + $this->doQuery( $pageId, $caller ); | |
| + } | |
| + if ( $this->misses === $this->missLimit ) { | |
| + // Log only once and don't bother incrementing beyond limit+1 | |
| + $this->misses++; | |
| + wfDebug( __METHOD__ . ': too many misses, returning default onwards' ); | |
| + } | |
| + } | |
| + | |
| + return $this->cache[$pageId] ?? []; | |
| + } | |
| + | |
| + /** | |
| + * Wrapper for doQuery that processes LinkBatch results. | |
| + * | |
| + * @param IResultWrapper $res | |
| + * @param string|null $caller | |
| + */ | |
| + public function doLinkBatch( $res, $caller = '' ) { | |
| + $pageIds = []; | |
| + foreach ( $res as $row ) { | |
| + $pageIds[] = (int)$row->page_id; | |
| + } | |
| + $this->doQuery( $pageIds, $caller ); | |
| + } | |
| + | |
| + /** | |
| + * Preload page properties for display title | |
| + * | |
| + * @param int[]|int $pageIds Page ids | |
| + * @param string|null $caller Calling method for database profiling | |
| + */ | |
| + public function doQuery( $pageIds, $caller = '' ) { | |
| + // Skip query when database is unavailable (e.g. via the installer) | |
| + if ( !$pageIds || !$this->dbProvider ) { | |
| + return; | |
| + } | |
| + | |
| + $caller = __METHOD__ . ( $caller ? "/$caller" : '' ); | |
| + | |
| + $res = $queryBuilder = $this->dbProvider->getReplicaDatabase()->newSelectQueryBuilder() | |
| + ->select( [ 'pp_page', 'pp_propname', 'pp_value' ] ) | |
| + ->from( 'page_props' ) | |
| + ->where( [ 'pp_page' => $pageIds, 'pp_propname' => self::PAGE_PROPERTIES ] ) | |
| + ->caller( $caller ) | |
| + ->fetchResultSet(); | |
| + | |
| + foreach ( $res as $row ) { | |
| + if ( array_key_exists( $row->pp_page, $this->cache ) ) { | |
| + $this->cache[$row->pp_page][$row->pp_propname] = $row->pp_value; | |
| + } else { | |
| + $this->cache[$row->pp_page] = [ $row->pp_propname => $row->pp_value ]; | |
| + } | |
| + } | |
| + | |
| + // Store pages without properties | |
| + $missing = array_diff( (array)$pageIds, array_keys( $this->cache ) ); | |
| + foreach ( $missing as $id ) { | |
| + $this->cache[$id] = []; | |
| + } | |
| + } | |
| +} | |
| diff --git a/includes/parser/LinkHolderArray.php b/includes/parser/LinkHolderArray.php | |
| index 0d763484d9e..63c1e631bc7 100644 | |
| --- a/includes/parser/LinkHolderArray.php | |
| +++ b/includes/parser/LinkHolderArray.php | |
| @@ -168,6 +168,7 @@ class LinkHolderArray { | |
| $classes = []; | |
| $services = MediaWikiServices::getInstance(); | |
| $linkCache = $services->getLinkCache(); | |
| + $pagePropsDisplayTitleCache = $services->getPagePropsDisplayTitleCache(); | |
| $output = $this->parent->getOutput(); | |
| $linkRenderer = $this->parent->getLinkRenderer(); | |
| @@ -214,6 +215,9 @@ class LinkHolderArray { | |
| ->caller( __METHOD__ ) | |
| ->fetchResultSet(); | |
| + // Why is this class duplicating what LinkCache does? IDK, but this forces me to add the PagePropsDisplayTitleCache call here too | |
| + $pagePropsDisplayTitleCache->doLinkBatch( $res ); | |
| + | |
| # Fetch data and form into an associative array | |
| # non-existent = broken | |
| foreach ( $res as $s ) { |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment