164 if ( !$this->internals ) {
170 $linkCache = $services->getLinkCache();
171 $output = $this->parent->getOutput();
172 $linkRenderer = $this->parent->getLinkRenderer();
174 $dbr = $services->getConnectionProvider()->getReplicaDatabase();
177 ksort( $this->internals );
182 $linkBatchFactory = $services->getLinkBatchFactory();
183 $lb = $linkBatchFactory->newLinkBatch();
184 $lb->setCaller( __METHOD__ );
186 foreach ( $this->internals as $ns => $entries ) {
187 foreach ( $entries as [
'title' => $title,
'pdbk' => $pdbk ] ) {
189 # Check if it's a static known link, e.g. interwiki
190 if ( $title->isAlwaysKnown() ) {
191 $classes[$pdbk] =
'';
193 $classes[$pdbk] =
'new';
195 $id = $linkCache->getGoodLinkID( $pdbk );
197 $classes[$pdbk] = $linkRenderer->getLinkClasses( $title );
198 $output->addLink( $title, $id );
199 $pagemap[$id] = $pdbk;
200 } elseif ( $linkCache->isBadLink( $pdbk ) ) {
201 $classes[$pdbk] =
'new';
203 # Not in the link cache, add it to the query
204 $lb->addObj( $title );
209 if ( !$lb->isEmpty() ) {
210 $res = $dbr->newSelectQueryBuilder()
211 ->select( LinkCache::getSelectFields() )
213 ->where( [ $lb->constructSet(
'page', $dbr ) ] )
214 ->caller( __METHOD__ )
217 # Fetch data and form into an associative array
218 # non-existent = broken
219 foreach ( $res as $s ) {
220 $title = Title::makeTitle( $s->page_namespace, $s->page_title );
221 $pdbk = $title->getPrefixedDBkey();
222 $linkCache->addGoodLinkObjFromRow( $title, $s );
223 $output->addLink( $title, $s->page_id );
224 $classes[$pdbk] = $linkRenderer->getLinkClasses( $title );
226 $pagemap[$s->page_id] = $pdbk;
230 if ( $pagemap !== [] ) {
232 $this->hookRunner->onGetLinkColours( $pagemap, $classes, $this->parent->getTitle() );
235 # Do a second query for different language variants of links and categories
236 if ( $this->languageConverter->hasVariants() ) {
240 # Construct search and replace arrays
242 foreach ( $this->internals as $ns => $entries ) {
243 foreach ( $entries as $index => $entry ) {
244 $pdbk = $entry[
'pdbk'];
245 $title = $entry[
'title'];
246 $query = $entry[
'query'] ?? [];
247 $searchkey =
"$ns:$index";
248 $displayTextHtml = $entry[
'text'];
249 if ( isset( $entry[
'selflink'] ) ) {
250 $replacePairs[$searchkey] = Linker::makeSelfLinkObj(
251 $title, $displayTextHtml, $query,
'',
'',
257 $displayText = $displayTextHtml ===
'' ? null :
new HtmlArmor( $displayTextHtml );
258 if ( !isset( $classes[$pdbk] ) ) {
259 $classes[$pdbk] =
'new';
261 if ( $classes[$pdbk] ===
'new' ) {
262 $linkCache->addBadLinkObj( $title );
263 $output->addLink( $title, 0 );
264 $link = $linkRenderer->makeBrokenLink(
265 $title, $displayText, [], $query
268 $link = $linkRenderer->makePreloadedLink(
269 $title, $displayText, $classes[$pdbk], [], $query
273 $replacePairs[$searchkey] = $link;
278 $text = preg_replace_callback(
279 '/<!--LINK\'" (-?[\d:]+)-->/',
280 static function ( array
$matches ) use ( $replacePairs ) {
320 $linkBatch = $linkBatchFactory->newLinkBatch();
322 $output = $this->parent->getOutput();
323 $titlesToBeConverted =
'';
329 foreach ( $this->internals as $ns => $entries ) {
333 foreach ( $entries as $index => [
'title' => $title,
'pdbk' => $pdbk ] ) {
335 if ( !isset( $classes[$pdbk] ) || $classes[$pdbk] ===
'new' ) {
336 $titlesAttrs[] = [ $index, $title ];
339 $titlesToBeConverted .= $title->getText() .
"\0";
345 $titlesAllVariants = $this->languageConverter->
346 autoConvertToAllVariants( rtrim( $titlesToBeConverted,
"\0" ) );
347 foreach ( $titlesAllVariants as &$titlesVariant ) {
348 $titlesVariant = explode(
"\0", $titlesVariant );
352 $parentTitle = $this->parent->getTitle();
353 foreach ( $titlesAttrs as $i => [ $index, $title ] ) {
355 $ns = $title->getNamespace();
356 $text = $title->getText();
358 foreach ( $titlesAllVariants as $textVariants ) {
359 $textVariant = $textVariants[$i];
360 if ( $textVariant === $text ) {
364 $variantTitle = Title::makeTitle( $ns, $textVariant );
369 if ( $variantTitle->equals( $parentTitle ) ) {
370 $this->internals[$ns][$index][
'selflink'] =
true;
374 $linkBatch->addObj( $variantTitle );
375 $variantMap[$variantTitle->getPrefixedDBkey()][] =
"$ns:$index";
381 foreach ( $output->getCategoryNames() as $category ) {
382 $categoryTitle = Title::makeTitleSafe(
NS_CATEGORY, $category );
383 $linkBatch->addObj( $categoryTitle );
384 $variants = $this->languageConverter->autoConvertToAllVariants( $category );
385 foreach ( $variants as $variant ) {
386 if ( $variant !== $category ) {
387 $variantTitle = Title::makeTitleSafe(
NS_CATEGORY, $variant );
388 if ( $variantTitle ) {
389 $linkBatch->addObj( $variantTitle );
390 $categoryMap[$variant] = [ $category, $categoryTitle ];
396 if ( $linkBatch->isEmpty() ) {
403 $varRes = $dbr->newSelectQueryBuilder()
404 ->select( LinkCache::getSelectFields() )
406 ->where( [ $linkBatch->constructSet(
'page', $dbr ) ] )
407 ->caller( __METHOD__ )
413 $linkRenderer = $this->parent->getLinkRenderer();
416 foreach ( $varRes as $s ) {
417 $variantTitle = Title::makeTitle( $s->page_namespace, $s->page_title );
418 $varPdbk = $variantTitle->getPrefixedDBkey();
420 if ( !isset( $variantMap[$varPdbk] ) ) {
424 $linkCache->addGoodLinkObjFromRow( $variantTitle, $s );
425 $output->addLink( $variantTitle, $s->page_id );
428 foreach ( $variantMap[$varPdbk] as $key ) {
429 [ $ns, $index ] = explode(
':', $key, 2 );
430 $entry =& $this->internals[(int)$ns][(
int)$index];
435 if ( isset( $entry[
'selflink'] ) ) {
439 $pdbk = $entry[
'pdbk'];
440 if ( !isset( $classes[$pdbk] ) || $classes[$pdbk] ===
'new' ) {
442 $entry[
'title'] = $variantTitle;
443 $entry[
'pdbk'] = $varPdbk;
446 if ( !isset( $classes[$varPdbk] ) ) {
447 $classes[$varPdbk] = $linkRenderer->getLinkClasses( $variantTitle );
448 $pagemap[$s->page_id] = $varPdbk;
454 $vardbk = $variantTitle->getDBkey();
455 if ( isset( $categoryMap[$vardbk] ) ) {
456 [ $oldkey, $oldtitle ] = $categoryMap[$vardbk];
457 if ( !isset( $varCategories[$oldkey] ) && !$oldtitle->exists() ) {
458 $varCategories[$oldkey] = $vardbk;
462 $this->hookRunner->onGetLinkColours( $pagemap, $classes, $this->parent->getTitle() );
465 if ( $varCategories !== [] ) {
467 foreach ( $output->getCategoryNames() as $cat ) {
468 $sortkey = $output->getCategorySortKey( $cat );
470 $newCats[$varCategories[$cat] ?? $cat] = $sortkey;
472 $output->setCategories( $newCats );