MediaWiki REL1_37
LinkBatch.php
Go to the documentation of this file.
1<?php
31use Wikimedia\Assert\Assert;
35
42class LinkBatch {
46 public $data = [];
47
51 private $pageIdentities = null;
52
56 protected $caller;
57
61 private $linkCache;
62
67
72
76 private $genderCache;
77
82
92 public function __construct(
93 iterable $arr = [],
94 ?LinkCache $linkCache = null,
95 ?TitleFormatter $titleFormatter = null,
96 ?Language $contentLanguage = null,
97 ?GenderCache $genderCache = null,
98 ?ILoadBalancer $loadBalancer = null
99 ) {
100 $getServices = static function () {
101 // BC hack. Use a closure so this can be unit-tested.
102 return MediaWikiServices::getInstance();
103 };
104
105 $this->linkCache = $linkCache ?? $getServices()->getLinkCache();
106 $this->titleFormatter = $titleFormatter ?? $getServices()->getTitleFormatter();
107 $this->contentLanguage = $contentLanguage ?? $getServices()->getContentLanguage();
108 $this->genderCache = $genderCache ?? $getServices()->getGenderCache();
109 $this->loadBalancer = $loadBalancer ?? $getServices()->getDBLoadBalancer();
110
111 foreach ( $arr as $item ) {
112 $this->addObj( $item );
113 }
114 }
115
124 public function setCaller( $caller ) {
125 $this->caller = $caller;
126
127 return $this;
128 }
129
133 public function addObj( $link ) {
134 if ( !$link ) {
135 // Don't die if we got null, just skip. There is nothing to do anyway.
136 // For now, let's avoid things like T282180. We should be more strict in the future.
137 LoggerFactory::getInstance( 'LinkBatch' )->warning(
138 'Skipping null link, probably due to a bad title.',
139 [ 'trace' => wfBacktrace( true ) ]
140 );
141 return;
142 }
143
144 Assert::parameterType( [ LinkTarget::class, PageReference::class ], $link, '$link' );
145 $this->add( $link->getNamespace(), $link->getDBkey() );
146 }
147
152 public function add( $ns, $dbkey ) {
153 if ( $ns < 0 || $dbkey === '' ) {
154 return; // T137083
155 }
156 if ( !array_key_exists( $ns, $this->data ) ) {
157 $this->data[$ns] = [];
158 }
159
160 $this->data[$ns][strtr( $dbkey, ' ', '_' )] = 1;
161 }
162
169 public function setArray( $array ) {
170 $this->data = $array;
171 }
172
178 public function isEmpty() {
179 return $this->getSize() == 0;
180 }
181
187 public function getSize() {
188 return count( $this->data );
189 }
190
196 public function execute() {
197 return $this->executeInto( $this->linkCache );
198 }
199
207 public function getPageIdentities(): array {
208 if ( $this->pageIdentities === null ) {
209 $this->execute();
210 }
211
212 return $this->pageIdentities;
213 }
214
222 protected function executeInto( $cache ) {
223 $res = $this->doQuery();
224 $this->doGenderQuery();
225 $ids = $this->addResultToCache( $cache, $res );
226
227 return $ids;
228 }
229
240 public function addResultToCache( $cache, $res ) {
241 if ( !$res ) {
242 return [];
243 }
244
245 // For each returned entry, add it to the list of good links, and remove it from $remaining
246
247 if ( $this->pageIdentities === null ) {
248 $this->pageIdentities = [];
249 }
250
251 $ids = [];
252 $remaining = $this->data;
253 foreach ( $res as $row ) {
254 try {
255 $title = new TitleValue( (int)$row->page_namespace, $row->page_title );
256
257 $cache->addGoodLinkObjFromRow( $title, $row );
258 $pdbk = $this->titleFormatter->getPrefixedDBkey( $title );
259 $ids[$pdbk] = $row->page_id;
260
261 $pageIdentity = new PageIdentityValue(
262 (int)$row->page_id,
263 (int)$row->page_namespace,
264 $row->page_title,
265 PageIdentity::LOCAL
266 );
267
268 $key = CacheKeyHelper::getKeyForPage( $pageIdentity );
269 $this->pageIdentities[$key] = $pageIdentity;
270 } catch ( InvalidArgumentException $ex ) {
271 LoggerFactory::getInstance( 'LinkBatch' )->warning(
272 'Encountered invalid title',
273 [ 'title_namespace' => $row->page_namespace, 'title_dbkey' => $row->page_title ]
274 );
275 }
276
277 unset( $remaining[$row->page_namespace][$row->page_title] );
278 }
279
280 // The remaining links in $data are bad links, register them as such
281 foreach ( $remaining as $ns => $dbkeys ) {
282 foreach ( $dbkeys as $dbkey => $unused ) {
283 try {
284 $title = new TitleValue( (int)$ns, (string)$dbkey );
285
286 $cache->addBadLinkObj( $title );
287 $pdbk = $this->titleFormatter->getPrefixedDBkey( $title );
288 $ids[$pdbk] = 0;
289
290 $pageIdentity = new PageIdentityValue( 0, (int)$ns, $dbkey, PageIdentity::LOCAL );
291 $key = CacheKeyHelper::getKeyForPage( $pageIdentity );
292 $this->pageIdentities[$key] = $pageIdentity;
293 } catch ( InvalidArgumentException $ex ) {
294 LoggerFactory::getInstance( 'LinkBatch' )->warning(
295 'Encountered invalid title',
296 [ 'title_namespace' => $ns, 'title_dbkey' => $dbkey ]
297 );
298 }
299 }
300 }
301
302 return $ids;
303 }
304
309 public function doQuery() {
310 if ( $this->isEmpty() ) {
311 return false;
312 }
313
314 // This is similar to LinkHolderArray::replaceInternal
315 $dbr = $this->loadBalancer->getConnectionRef( DB_REPLICA );
316 $table = 'page';
317 $fields = array_merge(
318 LinkCache::getSelectFields(),
319 [ 'page_namespace', 'page_title' ]
320 );
321
322 $conds = $this->constructSet( 'page', $dbr );
323
324 // Do query
325 $caller = __METHOD__;
326 if ( strval( $this->caller ) !== '' ) {
327 $caller .= " (for {$this->caller})";
328 }
329 $res = $dbr->select( $table, $fields, $conds, $caller );
330
331 return $res;
332 }
333
339 public function doGenderQuery() {
340 if ( $this->isEmpty() ) {
341 return false;
342 }
343
344 if ( !$this->contentLanguage->needsGenderDistinction() ) {
345 return false;
346 }
347
348 $this->genderCache->doLinkBatch( $this->data, $this->caller );
349
350 return true;
351 }
352
360 public function constructSet( $prefix, $db ) {
361 return $db->makeWhereFrom2d( $this->data, "{$prefix}_namespace", "{$prefix}_title" );
362 }
363}
wfBacktrace( $raw=null)
Get a debug backtrace as a string.
if(ini_get('mbstring.func_overload')) if(!defined('MW_ENTRY_POINT'))
Pre-config setup: Before loading LocalSettings.php.
Definition Setup.php:88
Caches user genders when needed to use correct namespace aliases.
Internationalisation code See https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation for more...
Definition Language.php:42
Class representing a list of titles The execute() method checks them all for existence and adds them ...
Definition LinkBatch.php:42
PageIdentity[] null $pageIdentities
PageIdentity objects corresponding to the links in the batch.
Definition LinkBatch.php:51
__construct(iterable $arr=[], ?LinkCache $linkCache=null, ?TitleFormatter $titleFormatter=null, ?Language $contentLanguage=null, ?GenderCache $genderCache=null, ?ILoadBalancer $loadBalancer=null)
Definition LinkBatch.php:92
doGenderQuery()
Do (and cache) {{GENDER:...}} information for userpages in this LinkBatch.
add( $ns, $dbkey)
ILoadBalancer $loadBalancer
Definition LinkBatch.php:81
getSize()
Returns the size of the batch.
GenderCache $genderCache
Definition LinkBatch.php:76
addObj( $link)
addResultToCache( $cache, $res)
Add a result wrapper containing IDs and titles to a LinkCache object.
isEmpty()
Returns true if no pages have been added, false otherwise.
setCaller( $caller)
Use ->setCaller( METHOD ) to indicate which code is using this class.
constructSet( $prefix, $db)
Construct a WHERE clause which will match all the given titles.
TitleFormatter $titleFormatter
Definition LinkBatch.php:66
getPageIdentities()
Do the query, add the results to the LinkCache object, and return PageIdentity instances correspondin...
LinkCache $linkCache
Definition LinkBatch.php:61
execute()
Do the query and add the results to the LinkCache object.
setArray( $array)
Set the link list to a given 2-d array First key is the namespace, second is the DB key,...
Language $contentLanguage
Definition LinkBatch.php:71
string null $caller
For debugging which method is using this class.
Definition LinkBatch.php:56
array[] $data
2-d array, first index namespace, second index dbkey, value arbitrary
Definition LinkBatch.php:46
executeInto( $cache)
Do the query and add the results to a given LinkCache object Return an array mapping PDBK to ID.
doQuery()
Perform the existence test query, return a result wrapper with page_id fields.
Cache for article titles (prefixed DB keys) and ids linked from one source.
Definition LinkCache.php:41
Helper class for mapping value objects representing basic entities to cache keys.
PSR-3 logger instance factory.
MediaWikiServices is the service locator for the application scope of MediaWiki.
Immutable value object representing a page identity.
Represents a page (or page fragment) title within MediaWiki.
Interface for objects (potentially) representing an editable wiki page.
Interface for objects (potentially) representing a page that can be viewable and linked to on a wiki.
A title formatter service for MediaWiki.
Basic database interface for live and lazy-loaded relation database handles.
Definition IDatabase.php:38
Database cluster connection, tracking, load balancing, and transaction manager interface.
Result wrapper for grabbing data queried from an IDatabase object.
$cache
Definition mcc.php:33
const DB_REPLICA
Definition defines.php:25