MediaWiki  master
LinkBatch.php
Go to the documentation of this file.
1 <?php
31 use Wikimedia\Assert\Assert;
35 
42 class LinkBatch {
46  public $data = [];
47 
51  private $pageIdentities = null;
52 
56  protected $caller;
57 
61  private $linkCache;
62 
66  private $titleFormatter;
67 
72 
76  private $genderCache;
77 
81  private $loadBalancer;
82 
92  public function __construct(
93  iterable $arr = [],
94  ?LinkCache $linkCache = null,
96  ?Language $contentLanguage = null,
97  ?GenderCache $genderCache = 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(
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 }
LinkBatch\$loadBalancer
ILoadBalancer $loadBalancer
Definition: LinkBatch.php:81
Page\PageIdentity
Interface for objects (potentially) representing an editable wiki page.
Definition: PageIdentity.php:64
LinkCache
Cache for article titles (prefixed DB keys) and ids linked from one source.
Definition: LinkCache.php:40
LinkBatch\doGenderQuery
doGenderQuery()
Do (and cache) {{GENDER:...}} information for userpages in this LinkBatch.
Definition: LinkBatch.php:339
LinkBatch\$titleFormatter
TitleFormatter $titleFormatter
Definition: LinkBatch.php:66
LinkBatch
Class representing a list of titles The execute() method checks them all for existence and adds them ...
Definition: LinkBatch.php:42
LinkBatch\add
add( $ns, $dbkey)
Definition: LinkBatch.php:152
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:193
LinkBatch\__construct
__construct(iterable $arr=[], ?LinkCache $linkCache=null, ?TitleFormatter $titleFormatter=null, ?Language $contentLanguage=null, ?GenderCache $genderCache=null, ?ILoadBalancer $loadBalancer=null)
Definition: LinkBatch.php:92
LinkBatch\setCaller
setCaller( $caller)
Use ->setCaller( METHOD ) to indicate which code is using this class.
Definition: LinkBatch.php:124
LinkBatch\addObj
addObj( $link)
Definition: LinkBatch.php:133
GenderCache
Caches user genders when needed to use correct namespace aliases.
Definition: GenderCache.php:36
LinkBatch\$caller
string null $caller
For debugging which method is using this class.
Definition: LinkBatch.php:56
LinkBatch\$linkCache
LinkCache $linkCache
Definition: LinkBatch.php:61
$res
$res
Definition: testCompression.php:57
LinkBatch\$pageIdentities
PageIdentity[] null $pageIdentities
PageIdentity objects corresponding to the links in the batch.
Definition: LinkBatch.php:51
LinkBatch\setArray
setArray( $array)
Set the link list to a given 2-d array First key is the namespace, second is the DB key,...
Definition: LinkBatch.php:169
Page\PageReference
Interface for objects (potentially) representing a page that can be viewable and linked to on a wiki.
Definition: PageReference.php:49
LinkCache\getSelectFields
static getSelectFields()
Fields that LinkCache needs to select.
Definition: LinkCache.php:382
LinkBatch\executeInto
executeInto( $cache)
Do the query and add the results to a given LinkCache object Return an array mapping PDBK to ID.
Definition: LinkBatch.php:222
Wikimedia\Rdbms\IDatabase
Basic database interface for live and lazy-loaded relation database handles.
Definition: IDatabase.php:38
LinkBatch\execute
execute()
Do the query and add the results to the LinkCache object.
Definition: LinkBatch.php:196
$dbr
$dbr
Definition: testCompression.php:54
LinkBatch\getSize
getSize()
Returns the size of the batch.
Definition: LinkBatch.php:187
MediaWiki\Logger\LoggerFactory
PSR-3 logger instance factory.
Definition: LoggerFactory.php:45
Wikimedia\Rdbms\IResultWrapper
Result wrapper for grabbing data queried from an IDatabase object.
Definition: IResultWrapper.php:26
LinkBatch\constructSet
constructSet( $prefix, $db)
Construct a WHERE clause which will match all the given titles.
Definition: LinkBatch.php:360
LinkBatch\$data
array[] $data
2-d array, first index namespace, second index dbkey, value arbitrary
Definition: LinkBatch.php:46
LinkBatch\$contentLanguage
Language $contentLanguage
Definition: LinkBatch.php:71
$title
$title
Definition: testCompression.php:38
DB_REPLICA
const DB_REPLICA
Definition: defines.php:25
LinkBatch\doQuery
doQuery()
Perform the existence test query, return a result wrapper with page_id fields.
Definition: LinkBatch.php:309
LinkBatch\isEmpty
isEmpty()
Returns true if no pages have been added, false otherwise.
Definition: LinkBatch.php:178
LinkBatch\getPageIdentities
getPageIdentities()
Do the query, add the results to the LinkCache object, and return PageIdentity instances correspondin...
Definition: LinkBatch.php:207
$cache
$cache
Definition: mcc.php:33
TitleFormatter
A title formatter service for MediaWiki.
Definition: TitleFormatter.php:35
MediaWiki\Cache\CacheKeyHelper
Helper class for mapping value objects representing basic entities to cache keys.
Definition: CacheKeyHelper.php:43
Page\PageIdentityValue
Immutable value object representing a page identity.
Definition: PageIdentityValue.php:41
wfBacktrace
wfBacktrace( $raw=null)
Get a debug backtrace as a string.
Definition: GlobalFunctions.php:1326
MediaWiki\Linker\LinkTarget
Definition: LinkTarget.php:26
LinkBatch\addResultToCache
addResultToCache( $cache, $res)
Add a result wrapper containing IDs and titles to a LinkCache object.
Definition: LinkBatch.php:240
LinkBatch\$genderCache
GenderCache $genderCache
Definition: LinkBatch.php:76
Language
Internationalisation code See https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation for more...
Definition: Language.php:42
Wikimedia\Rdbms\ILoadBalancer
Database cluster connection, tracking, load balancing, and transaction manager interface.
Definition: ILoadBalancer.php:81
TitleValue
Represents a page (or page fragment) title within MediaWiki.
Definition: TitleValue.php:40