161 if ( !$this->internals ) {
166 $services = MediaWikiServices::getInstance();
167 $linkCache = $services->getLinkCache();
168 $output = $this->parent->getOutput();
169 $linkRenderer = $this->parent->getLinkRenderer();
171 $dbr = $services->getConnectionProvider()->getReplicaDatabase();
174 ksort( $this->internals );
179 $linkBatchFactory = $services->getLinkBatchFactory();
180 $lb = $linkBatchFactory->newLinkBatch();
181 $lb->setCaller( __METHOD__ );
183 foreach ( $this->internals as $ns => $entries ) {
184 foreach ( $entries as [
'title' => $title,
'pdbk' => $pdbk ] ) {
186 # Check if it's a static known link, e.g. interwiki
187 if ( $title->isAlwaysKnown() ) {
188 $classes[$pdbk] =
'';
190 $classes[$pdbk] =
'new';
192 $id = $linkCache->getGoodLinkID( $pdbk );
194 $classes[$pdbk] = $linkRenderer->getLinkClasses( $title );
195 $output->addLink( $title, $id );
196 $pagemap[$id] = $pdbk;
197 } elseif ( $linkCache->isBadLink( $pdbk ) ) {
198 $classes[$pdbk] =
'new';
200 # Not in the link cache, add it to the query
201 $lb->addObj( $title );
206 if ( !$lb->isEmpty() ) {
207 $res = $dbr->newSelectQueryBuilder()
208 ->select( LinkCache::getSelectFields() )
210 ->where( [ $lb->constructSet(
'page', $dbr ) ] )
211 ->caller( __METHOD__ )
214 # Fetch data and form into an associative array
215 # non-existent = broken
216 foreach ( $res as $s ) {
217 $title = Title::makeTitle( $s->page_namespace, $s->page_title );
218 $pdbk = $title->getPrefixedDBkey();
219 $linkCache->addGoodLinkObjFromRow( $title, $s );
220 $output->addLink( $title, $s->page_id );
221 $classes[$pdbk] = $linkRenderer->getLinkClasses( $title );
223 $pagemap[$s->page_id] = $pdbk;
227 if ( $pagemap !== [] ) {
229 $this->hookRunner->onGetLinkColours( $pagemap, $classes, $this->parent->getTitle() );
232 # Do a second query for different language variants of links and categories
233 if ( $this->languageConverter->hasVariants() ) {
237 # Construct search and replace arrays
239 foreach ( $this->internals as $ns => $entries ) {
240 foreach ( $entries as $index => $entry ) {
241 $pdbk = $entry[
'pdbk'];
242 $title = $entry[
'title'];
243 $query = $entry[
'query'] ?? [];
244 $searchkey =
"$ns:$index";
245 $displayTextHtml = $entry[
'text'];
246 if ( isset( $entry[
'selflink'] ) ) {
247 $replacePairs[$searchkey] = Linker::makeSelfLinkObj( $title, $displayTextHtml, $query );
251 $displayText = $displayTextHtml ===
'' ? null :
new HtmlArmor( $displayTextHtml );
252 if ( !isset( $classes[$pdbk] ) ) {
253 $classes[$pdbk] =
'new';
255 if ( $classes[$pdbk] ===
'new' ) {
256 $linkCache->addBadLinkObj( $title );
257 $output->addLink( $title, 0 );
258 $link = $linkRenderer->makeBrokenLink(
259 $title, $displayText, [], $query
262 $link = $linkRenderer->makePreloadedLink(
263 $title, $displayText, $classes[$pdbk], [], $query
267 $replacePairs[$searchkey] = $link;
272 $text = preg_replace_callback(
273 '/<!--LINK\'" (-?[\d:]+)-->/',
274 static function ( array
$matches ) use ( $replacePairs ) {
313 $linkBatchFactory = MediaWikiServices::getInstance()->getLinkBatchFactory();
314 $linkBatch = $linkBatchFactory->newLinkBatch();
316 $output = $this->parent->getOutput();
317 $titlesToBeConverted =
'';
323 foreach ( $this->internals as $ns => $entries ) {
327 foreach ( $entries as $index => [
'title' => $title,
'pdbk' => $pdbk ] ) {
329 if ( !isset( $classes[$pdbk] ) || $classes[$pdbk] ===
'new' ) {
330 $titlesAttrs[] = [ $index, $title ];
333 $titlesToBeConverted .= $title->getText() .
"\0";
339 $titlesAllVariants = $this->languageConverter->
340 autoConvertToAllVariants( rtrim( $titlesToBeConverted,
"\0" ) );
341 foreach ( $titlesAllVariants as &$titlesVariant ) {
342 $titlesVariant = explode(
"\0", $titlesVariant );
346 $parentTitle = $this->parent->getTitle();
347 foreach ( $titlesAttrs as $i => [ $index, $title ] ) {
349 $ns = $title->getNamespace();
350 $text = $title->getText();
352 foreach ( $titlesAllVariants as $textVariants ) {
353 $textVariant = $textVariants[$i];
354 if ( $textVariant === $text ) {
358 $variantTitle = Title::makeTitle( $ns, $textVariant );
363 if ( $variantTitle->equals( $parentTitle ) && !$title->hasFragment() ) {
364 $this->internals[$ns][$index][
'selflink'] =
true;
368 $linkBatch->addObj( $variantTitle );
369 $variantMap[$variantTitle->getPrefixedDBkey()][] =
"$ns:$index";
375 foreach ( $output->getCategoryNames() as $category ) {
376 $categoryTitle = Title::makeTitleSafe(
NS_CATEGORY, $category );
377 $linkBatch->addObj( $categoryTitle );
378 $variants = $this->languageConverter->autoConvertToAllVariants( $category );
379 foreach ( $variants as $variant ) {
380 if ( $variant !== $category ) {
381 $variantTitle = Title::makeTitleSafe(
NS_CATEGORY, $variant );
382 if ( $variantTitle ) {
383 $linkBatch->addObj( $variantTitle );
384 $categoryMap[$variant] = [ $category, $categoryTitle ];
390 if ( $linkBatch->isEmpty() ) {
395 $dbr = MediaWikiServices::getInstance()->getConnectionProvider()->getReplicaDatabase();
397 $varRes = $dbr->newSelectQueryBuilder()
398 ->select( LinkCache::getSelectFields() )
400 ->where( [ $linkBatch->constructSet(
'page', $dbr ) ] )
401 ->caller( __METHOD__ )
406 $linkCache = MediaWikiServices::getInstance()->getLinkCache();
407 $linkRenderer = $this->parent->getLinkRenderer();
410 foreach ( $varRes as $s ) {
411 $variantTitle = Title::makeTitle( $s->page_namespace, $s->page_title );
412 $varPdbk = $variantTitle->getPrefixedDBkey();
414 if ( !isset( $variantMap[$varPdbk] ) ) {
418 $linkCache->addGoodLinkObjFromRow( $variantTitle, $s );
419 $output->addLink( $variantTitle, $s->page_id );
422 foreach ( $variantMap[$varPdbk] as $key ) {
423 [ $ns, $index ] = explode(
':', $key, 2 );
424 $entry =& $this->internals[(int)$ns][(
int)$index];
425 $pdbk = $entry[
'pdbk'];
427 if ( !isset( $classes[$pdbk] ) || $classes[$pdbk] ===
'new' ) {
429 $entry[
'title'] = $variantTitle;
430 $entry[
'pdbk'] = $varPdbk;
433 if ( !isset( $classes[$varPdbk] ) ) {
434 $classes[$varPdbk] = $linkRenderer->getLinkClasses( $variantTitle );
435 $pagemap[$s->page_id] = $varPdbk;
441 $vardbk = $variantTitle->getDBkey();
442 if ( isset( $categoryMap[$vardbk] ) ) {
443 [ $oldkey, $oldtitle ] = $categoryMap[$vardbk];
444 if ( !isset( $varCategories[$oldkey] ) && !$oldtitle->exists() ) {
445 $varCategories[$oldkey] = $vardbk;
449 $this->hookRunner->onGetLinkColours( $pagemap, $classes, $this->parent->getTitle() );
452 if ( $varCategories !== [] ) {
454 foreach ( $output->getCategoryNames() as $cat ) {
455 $sortkey = $output->getCategorySortKey( $cat );
457 $newCats[$varCategories[$cat] ?? $cat] = $sortkey;
459 $output->setCategories( $newCats );