Move deduplication of language links out of Parser.php and into the ParserOutput in order to be compatible with alternate Parsers (Parsoid). Clean up various inconsistencies: ensure deduplication also happens in OutputPage when multiple ParserOutputs are merged into the final output, and ensure that the deduplication in LinksUpdate is done in the same order (first link prevails) as in Parser/ParserOutput/OutputPage. Deprecate OutputPage::setLanguageLinks() (the matching ParserOutput::setLanguageLinks() was deprecated in 1.42). As a breaking change, return an array, not an array *reference*, from ParserOutput::getLanguageLinks(). This allows us to safely modify the internal representation of language links. As far as I can tell, no one used the returned reference to sneakily modify the list of language links, and there not a good way to have deprecated this before making the breaking change. While we're at it, we've added tests to ensure that language link fragments are preserved. Bug: T26502 Bug: T358950 Bug: T375005 Change-Id: I82a05a51d94782ebb9fa87ff889ca0f633b3e15c
102 lines
2.4 KiB
PHP
102 lines
2.4 KiB
PHP
<?php
|
|
|
|
namespace MediaWiki\Deferred\LinksUpdate;
|
|
|
|
use MediaWiki\Parser\ParserOutput;
|
|
|
|
/**
|
|
* langlinks
|
|
*
|
|
* Link ID format: string[]
|
|
* - 0: Language code
|
|
* - 1: Foreign title
|
|
*
|
|
* @since 1.38
|
|
*/
|
|
class LangLinksTable extends LinksTable {
|
|
/** @var string[] */
|
|
private $newLinks = [];
|
|
/** @var string[]|null */
|
|
private $existingLinks;
|
|
|
|
public function setParserOutput( ParserOutput $parserOutput ) {
|
|
// Convert the format of the interlanguage links
|
|
// I didn't want to change it in the ParserOutput, because that array is passed all
|
|
// the way back to the skin, so either a skin API break would be required, or an
|
|
// inefficient back-conversion.
|
|
$ill = $parserOutput->getLanguageLinks();
|
|
$this->newLinks = [];
|
|
foreach ( $ill as $link ) {
|
|
[ $key, $title ] = explode( ':', $link, 2 );
|
|
// Ensure that the "first" link has precedence: T26502
|
|
$this->newLinks[$key] ??= $title;
|
|
}
|
|
}
|
|
|
|
protected function getTableName() {
|
|
return 'langlinks';
|
|
}
|
|
|
|
protected function getFromField() {
|
|
return 'll_from';
|
|
}
|
|
|
|
protected function getExistingFields() {
|
|
return [ 'll_lang', 'll_title' ];
|
|
}
|
|
|
|
protected function getNewLinkIDs() {
|
|
foreach ( $this->newLinks as $key => $title ) {
|
|
yield [ (string)$key, $title ];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the existing links as an array where the key is the language code
|
|
* and the value is the title of the target in that language.
|
|
*
|
|
* @return array
|
|
*/
|
|
private function getExistingLinks() {
|
|
if ( $this->existingLinks === null ) {
|
|
$this->existingLinks = [];
|
|
foreach ( $this->fetchExistingRows() as $row ) {
|
|
$this->existingLinks[$row->ll_lang] = $row->ll_title;
|
|
}
|
|
}
|
|
return $this->existingLinks;
|
|
}
|
|
|
|
protected function getExistingLinkIDs() {
|
|
foreach ( $this->getExistingLinks() as $lang => $title ) {
|
|
yield [ (string)$lang, $title ];
|
|
}
|
|
}
|
|
|
|
protected function isExisting( $linkId ) {
|
|
$links = $this->getExistingLinks();
|
|
[ $lang, $title ] = $linkId;
|
|
return \array_key_exists( $lang, $links )
|
|
&& $links[$lang] === $title;
|
|
}
|
|
|
|
protected function isInNewSet( $linkId ) {
|
|
[ $lang, $title ] = $linkId;
|
|
return \array_key_exists( $lang, $this->newLinks )
|
|
&& $this->newLinks[$lang] === $title;
|
|
}
|
|
|
|
protected function insertLink( $linkId ) {
|
|
[ $lang, $title ] = $linkId;
|
|
$this->insertRow( [
|
|
'll_lang' => $lang,
|
|
'll_title' => $title
|
|
] );
|
|
}
|
|
|
|
protected function deleteLink( $linkId ) {
|
|
$this->deleteRow( [
|
|
'll_lang' => $linkId[0]
|
|
] );
|
|
}
|
|
}
|