140 if ( !$this->internals ) {
146 $linkCache = $services->getLinkCache();
147 $output = $this->parent->getOutput();
148 $linkRenderer = $this->parent->getLinkRenderer();
150 $dbr = $services->getConnectionProvider()->getReplicaDatabase();
153 ksort( $this->internals );
158 $linkBatchFactory = $services->getLinkBatchFactory();
159 $lb = $linkBatchFactory->newLinkBatch();
160 $lb->setCaller( __METHOD__ );
162 foreach ( $this->internals as $ns => $entries ) {
163 foreach ( $entries as [
'title' => $title,
'pdbk' => $pdbk ] ) {
165 # Check if it's a static known link, e.g. interwiki
166 if ( $title->isAlwaysKnown() ) {
167 $classes[$pdbk] =
'';
169 $classes[$pdbk] =
'new';
171 $id = $linkCache->getGoodLinkID( $pdbk );
173 $classes[$pdbk] = $linkRenderer->getLinkClasses( $title );
174 $output->addLink( $title, $id );
175 $pagemap[$id] = $pdbk;
176 } elseif ( $linkCache->isBadLink( $pdbk ) ) {
177 $classes[$pdbk] =
'new';
179 # Not in the link cache, add it to the query
180 $lb->addObj( $title );
185 if ( !$lb->isEmpty() ) {
186 $res = $dbr->newSelectQueryBuilder()
187 ->select( LinkCache::getSelectFields() )
189 ->where( [ $lb->constructSet(
'page', $dbr ) ] )
190 ->caller( __METHOD__ )
193 # Fetch data and form into an associative array
194 # non-existent = broken
195 foreach ( $res as $s ) {
197 $pdbk = $title->getPrefixedDBkey();
198 $linkCache->addGoodLinkObjFromRow( $title, $s );
199 $output->addLink( $title, $s->page_id );
200 $classes[$pdbk] = $linkRenderer->getLinkClasses( $title );
202 $pagemap[$s->page_id] = $pdbk;
206 if ( $pagemap !== [] ) {
208 $this->hookRunner->onGetLinkColours( $pagemap, $classes, $this->parent->getTitle() );
211 # Do a second query for different language variants of links and categories
212 if ( $this->languageConverter->hasVariants() ) {
216 # Construct search and replace arrays
218 foreach ( $this->internals as $ns => $entries ) {
219 foreach ( $entries as $index => $entry ) {
220 $pdbk = $entry[
'pdbk'];
221 $title = $entry[
'title'];
222 $query = $entry[
'query'] ?? [];
223 $searchkey =
"$ns:$index";
224 $displayTextHtml = $entry[
'text'];
225 if ( isset( $entry[
'selflink'] ) ) {
226 $replacePairs[$searchkey] = Linker::makeSelfLinkObj(
227 $title, $displayTextHtml, $query,
'',
'',
233 $displayText = $displayTextHtml ===
'' ? null :
new HtmlArmor( $displayTextHtml );
234 if ( !isset( $classes[$pdbk] ) ) {
235 $classes[$pdbk] =
'new';
237 if ( $classes[$pdbk] ===
'new' ) {
238 $linkCache->addBadLinkObj( $title );
239 $output->addLink( $title, 0 );
240 $link = $linkRenderer->makeBrokenLink(
241 $title, $displayText, [], $query
244 $link = $linkRenderer->makePreloadedLink(
245 $title, $displayText, $classes[$pdbk], [], $query
249 $replacePairs[$searchkey] = $link;
254 $text = preg_replace_callback(
255 '/<!--LINK\'" (-?[\d:]+)-->/',
256 static function ( array
$matches ) use ( $replacePairs ) {
296 $linkBatch = $linkBatchFactory->newLinkBatch();
298 $output = $this->parent->getOutput();
299 $titlesToBeConverted =
'';
305 foreach ( $this->internals as $ns => $entries ) {
309 foreach ( $entries as $index => [
'title' => $title,
'pdbk' => $pdbk ] ) {
311 if ( !isset( $classes[$pdbk] ) || $classes[$pdbk] ===
'new' ) {
312 $titlesAttrs[] = [ $index, $title ];
315 $titlesToBeConverted .= $title->getText() .
"\0";
321 $titlesAllVariants = $this->languageConverter->
322 autoConvertToAllVariants( rtrim( $titlesToBeConverted,
"\0" ) );
323 foreach ( $titlesAllVariants as &$titlesVariant ) {
324 $titlesVariant = explode(
"\0", $titlesVariant );
328 $parentTitle = $this->parent->getTitle();
329 foreach ( $titlesAttrs as $i => [ $index, $title ] ) {
331 $ns = $title->getNamespace();
332 $text = $title->getText();
334 foreach ( $titlesAllVariants as $textVariants ) {
335 $textVariant = $textVariants[$i];
336 if ( $textVariant === $text ) {
345 if ( $variantTitle->equals( $parentTitle ) ) {
346 $this->internals[$ns][$index][
'selflink'] =
true;
350 $linkBatch->addObj( $variantTitle );
351 $variantMap[$variantTitle->getPrefixedDBkey()][] =
"$ns:$index";
357 foreach ( $output->getCategoryNames() as $category ) {
358 $categoryTitle = Title::makeTitleSafe(
NS_CATEGORY, $category );
359 $linkBatch->addObj( $categoryTitle );
360 $variants = $this->languageConverter->autoConvertToAllVariants( $category );
361 foreach ( $variants as $variant ) {
362 if ( $variant !== $category ) {
363 $variantTitle = Title::makeTitleSafe(
NS_CATEGORY, $variant );
364 if ( $variantTitle ) {
365 $linkBatch->addObj( $variantTitle );
366 $categoryMap[$variant] = [ $category, $categoryTitle ];
372 if ( $linkBatch->isEmpty() ) {
379 $varRes = $dbr->newSelectQueryBuilder()
380 ->select( LinkCache::getSelectFields() )
382 ->where( [ $linkBatch->constructSet(
'page', $dbr ) ] )
383 ->caller( __METHOD__ )
389 $linkRenderer = $this->parent->getLinkRenderer();
392 foreach ( $varRes as $s ) {
394 $varPdbk = $variantTitle->getPrefixedDBkey();
396 if ( !isset( $variantMap[$varPdbk] ) ) {
400 $linkCache->addGoodLinkObjFromRow( $variantTitle, $s );
401 $output->addLink( $variantTitle, $s->page_id );
404 foreach ( $variantMap[$varPdbk] as $key ) {
405 [ $ns, $index ] = explode(
':', $key, 2 );
406 $entry =& $this->internals[(int)$ns][(
int)$index];
411 if ( isset( $entry[
'selflink'] ) ) {
415 $pdbk = $entry[
'pdbk'];
416 if ( !isset( $classes[$pdbk] ) || $classes[$pdbk] ===
'new' ) {
418 $entry[
'title'] = $variantTitle;
419 $entry[
'pdbk'] = $varPdbk;
422 if ( !isset( $classes[$varPdbk] ) ) {
423 $classes[$varPdbk] = $linkRenderer->getLinkClasses( $variantTitle );
424 $pagemap[$s->page_id] = $varPdbk;
430 $vardbk = $variantTitle->getDBkey();
431 if ( isset( $categoryMap[$vardbk] ) ) {
432 [ $oldkey, $oldtitle ] = $categoryMap[$vardbk];
433 if ( !isset( $varCategories[$oldkey] ) && !$oldtitle->exists() ) {
434 $varCategories[$oldkey] = $vardbk;
438 $this->hookRunner->onGetLinkColours( $pagemap, $classes, $this->parent->getTitle() );
441 if ( $varCategories !== [] ) {
443 foreach ( $output->getCategoryNames() as $cat ) {
444 $sortkey = $output->getCategorySortKey( $cat );
446 $newCats[$varCategories[$cat] ?? $cat] = $sortkey;
448 $output->setCategories( $newCats );