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  // T137083
155  return;
156  }
157  if ( !array_key_exists( $ns, $this->data ) ) {
158  $this->data[$ns] = [];
159  }
160 
161  $this->data[$ns][strtr( $dbkey, ' ', '_' )] = 1;
162  }
163 
170  public function setArray( $array ) {
171  $this->data = $array;
172  }
173 
179  public function isEmpty() {
180  return $this->getSize() == 0;
181  }
182 
188  public function getSize() {
189  return count( $this->data );
190  }
191 
197  public function execute() {
198  return $this->executeInto( $this->linkCache );
199  }
200 
208  public function getPageIdentities(): array {
209  if ( $this->pageIdentities === null ) {
210  $this->execute();
211  }
212 
213  return $this->pageIdentities;
214  }
215 
223  protected function executeInto( $cache ) {
224  $res = $this->doQuery();
225  $this->doGenderQuery();
226  return $this->addResultToCache( $cache, $res );
227  }
228 
239  public function addResultToCache( $cache, $res ) {
240  if ( !$res ) {
241  return [];
242  }
243 
244  // For each returned entry, add it to the list of good links, and remove it from $remaining
245 
246  if ( $this->pageIdentities === null ) {
247  $this->pageIdentities = [];
248  }
249 
250  $ids = [];
251  $remaining = $this->data;
252  foreach ( $res as $row ) {
253  try {
254  $title = new TitleValue( (int)$row->page_namespace, $row->page_title );
255 
256  $cache->addGoodLinkObjFromRow( $title, $row );
257  $pdbk = $this->titleFormatter->getPrefixedDBkey( $title );
258  $ids[$pdbk] = $row->page_id;
259 
260  $pageIdentity = new PageIdentityValue(
261  (int)$row->page_id,
262  (int)$row->page_namespace,
263  $row->page_title,
264  PageIdentity::LOCAL
265  );
266 
267  $key = CacheKeyHelper::getKeyForPage( $pageIdentity );
268  $this->pageIdentities[$key] = $pageIdentity;
269  } catch ( InvalidArgumentException $ex ) {
270  LoggerFactory::getInstance( 'LinkBatch' )->warning(
271  'Encountered invalid title',
272  [ 'title_namespace' => $row->page_namespace, 'title_dbkey' => $row->page_title ]
273  );
274  }
275 
276  unset( $remaining[$row->page_namespace][$row->page_title] );
277  }
278 
279  // The remaining links in $data are bad links, register them as such
280  foreach ( $remaining as $ns => $dbkeys ) {
281  foreach ( $dbkeys as $dbkey => $unused ) {
282  try {
283  $title = new TitleValue( (int)$ns, (string)$dbkey );
284 
285  $cache->addBadLinkObj( $title );
286  $pdbk = $this->titleFormatter->getPrefixedDBkey( $title );
287  $ids[$pdbk] = 0;
288 
289  $pageIdentity = new PageIdentityValue( 0, (int)$ns, $dbkey, PageIdentity::LOCAL );
290  $key = CacheKeyHelper::getKeyForPage( $pageIdentity );
291  $this->pageIdentities[$key] = $pageIdentity;
292  } catch ( InvalidArgumentException $ex ) {
293  LoggerFactory::getInstance( 'LinkBatch' )->warning(
294  'Encountered invalid title',
295  [ 'title_namespace' => $ns, 'title_dbkey' => $dbkey ]
296  );
297  }
298  }
299  }
300 
301  return $ids;
302  }
303 
308  public function doQuery() {
309  if ( $this->isEmpty() ) {
310  return false;
311  }
312 
313  // This is similar to LinkHolderArray::replaceInternal
314  $dbr = $this->loadBalancer->getConnectionRef( DB_REPLICA );
315  $table = 'page';
316  $fields = array_merge(
318  [ 'page_namespace', 'page_title' ]
319  );
320 
321  $conds = $this->constructSet( 'page', $dbr );
322 
323  // Do query
324  $caller = __METHOD__;
325  if ( strval( $this->caller ) !== '' ) {
326  $caller .= " (for {$this->caller})";
327  }
328 
329  return $dbr->select( $table, $fields, $conds, $caller );
330  }
331 
337  public function doGenderQuery() {
338  if ( $this->isEmpty() ) {
339  return false;
340  }
341 
342  if ( !$this->contentLanguage->needsGenderDistinction() ) {
343  return false;
344  }
345 
346  $this->genderCache->doLinkBatch( $this->data, $this->caller );
347 
348  return true;
349  }
350 
358  public function constructSet( $prefix, $db ) {
359  return $db->makeWhereFrom2d( $this->data, "{$prefix}_namespace", "{$prefix}_title" );
360  }
361 }
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:41
LinkBatch\doGenderQuery
doGenderQuery()
Do (and cache) {{GENDER:...}} information for userpages in this LinkBatch.
Definition: LinkBatch.php:337
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:204
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:170
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:384
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:223
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:197
$dbr
$dbr
Definition: testCompression.php:54
LinkBatch\getSize
getSize()
Returns the size of the batch.
Definition: LinkBatch.php:188
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:358
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:308
LinkBatch\isEmpty
isEmpty()
Returns true if no pages have been added, false otherwise.
Definition: LinkBatch.php:179
LinkBatch\getPageIdentities
getPageIdentities()
Do the query, add the results to the LinkCache object, and return PageIdentity instances correspondin...
Definition: LinkBatch.php:208
$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:1307
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:239
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