These three classes: - TitleArray - TitleArrayFromResult - TitleFactory We need to move these and the rest of files under title/ to Title/ (and namespace them) but the patch will become way too big given that Title class is also one of them. Bug: T321882 Change-Id: Iac1688172ee457348a08a470c86e047571feb8e0
423 lines
12 KiB
PHP
423 lines
12 KiB
PHP
<?php
|
|
|
|
namespace MediaWiki\Parser\Parsoid;
|
|
|
|
use Language;
|
|
use MediaWiki\Languages\LanguageFactory;
|
|
use MediaWiki\Page\PageIdentity;
|
|
use MediaWiki\Page\PageIdentityValue;
|
|
use MediaWiki\Parser\Parsoid\Config\PageConfig;
|
|
use MediaWiki\Parser\Parsoid\Config\PageConfigFactory;
|
|
use MediaWiki\Parser\Parsoid\Config\SiteConfig;
|
|
use MediaWiki\Title\TitleFactory;
|
|
use MediaWikiUnitTestCase;
|
|
use PHPUnit\Framework\MockObject\MockObject;
|
|
use Title;
|
|
use Wikimedia\Parsoid\Core\PageBundle;
|
|
use Wikimedia\Parsoid\Parsoid;
|
|
|
|
/**
|
|
* @covers MediaWiki\Parser\Parsoid\LanguageVariantConverter
|
|
*/
|
|
class LanguageVariantConverterUnitTest extends MediaWikiUnitTestCase {
|
|
|
|
/** @dataProvider provideSetConfig */
|
|
public function testSetConfig( bool $shouldPageConfigFactoryBeUsed ) {
|
|
// Decide what should be called and what should not be
|
|
$shouldParsoidBeUsed = true;
|
|
$isLanguageConversionEnabled = true;
|
|
|
|
// Set expected language codes
|
|
$pageBundleLanguageCode = 'zh';
|
|
$titleLanguageCode = 'zh-hans';
|
|
$targetLanguageCode = 'zh-hans';
|
|
$sourceLanguageCode = null;
|
|
|
|
// Create mocks
|
|
$parsoidSettings = [];
|
|
$pageConfigMock = $this->getPageConfigMock();
|
|
$pageBundleMock = $this->getPageBundleMock( $pageBundleLanguageCode );
|
|
|
|
$languageVariantConverter = $this->getLanguageVariantConverter(
|
|
$shouldParsoidBeUsed,
|
|
$shouldPageConfigFactoryBeUsed,
|
|
$isLanguageConversionEnabled,
|
|
$pageBundleLanguageCode,
|
|
null,
|
|
$titleLanguageCode,
|
|
$targetLanguageCode,
|
|
$sourceLanguageCode,
|
|
$parsoidSettings
|
|
);
|
|
|
|
if ( !$shouldPageConfigFactoryBeUsed ) {
|
|
$languageVariantConverter->setPageConfig( $pageConfigMock );
|
|
}
|
|
|
|
$languageVariantConverter->convertPageBundleVariant( $pageBundleMock, $targetLanguageCode );
|
|
}
|
|
|
|
public function provideSetConfig() {
|
|
yield 'PageConfigFactory should not be used if PageConfig is set' => [ false ];
|
|
|
|
yield 'PageConfigFactory should be used if PageConfig is not set' => [ true ];
|
|
}
|
|
|
|
/** @dataProvider provideSourceLanguage */
|
|
public function testSourceLanguage(
|
|
?string $pageBundleLanguageCode,
|
|
?string $titleLanguageCode,
|
|
?string $contentLanguageOverride,
|
|
?string $sourceLanguageCode,
|
|
?string $expectedSourceCode
|
|
) {
|
|
// Decide what should be called and what should not be
|
|
$shouldParsoidBeUsed = true;
|
|
$shouldPageConfigFactoryBeUsed = true;
|
|
$isLanguageConversionEnabled = true;
|
|
|
|
// Set expected language codes
|
|
$titleLanguageCode = $titleLanguageCode ?? 'en';
|
|
$targetLanguageCode = 'en-us';
|
|
|
|
$parsoidSettings = [];
|
|
// Create mocks
|
|
if ( $pageBundleLanguageCode ) {
|
|
$pageBundleMock = $this->getPageBundleMock( $pageBundleLanguageCode );
|
|
} else {
|
|
$pageBundleMock = $this->getPageBundleMockWithoutLanguage();
|
|
}
|
|
|
|
$languageVariantConverter = $this->getLanguageVariantConverter(
|
|
$shouldParsoidBeUsed,
|
|
$shouldPageConfigFactoryBeUsed,
|
|
$isLanguageConversionEnabled,
|
|
$pageBundleLanguageCode,
|
|
$contentLanguageOverride,
|
|
$titleLanguageCode,
|
|
$targetLanguageCode,
|
|
$expectedSourceCode,
|
|
$parsoidSettings
|
|
);
|
|
|
|
$languageVariantConverter->convertPageBundleVariant( $pageBundleMock, $targetLanguageCode, $sourceLanguageCode );
|
|
}
|
|
|
|
public function provideSourceLanguage() {
|
|
yield 'content-language in PageBundle' => [
|
|
'sr-el', // PageBundle content-language
|
|
null, // Title PageLanguage
|
|
null, // PageLanguage override
|
|
'sr-ec', // explicit source
|
|
'sr-ec' // expected source
|
|
];
|
|
yield 'content-language but no source language' => [
|
|
'en', // PageBundle content-language
|
|
null, // Title PageLanguage
|
|
null, // PageLanguage override
|
|
null, // explicit source
|
|
null // expected source
|
|
];
|
|
yield 'content-language is variant' => [
|
|
'en-ca', // PageBundle content-language
|
|
null, // Title PageLanguage
|
|
null, // PageLanguage override
|
|
null, // explicit source
|
|
'en-ca' // expected source
|
|
];
|
|
yield 'Source variant is given' => [
|
|
null, // PageBundle content-language
|
|
null, // Title PageLanguage
|
|
null, // PageLanguage override
|
|
'en-ca', // explicit source
|
|
'en-ca' // expected source
|
|
];
|
|
yield 'Source variant is a base language' => [
|
|
null, // PageBundle content-language
|
|
null, // Title PageLanguage
|
|
null, // PageLanguage override
|
|
'en', // explicit source
|
|
null // expected source
|
|
];
|
|
yield 'Page language override is variant' => [
|
|
null, // PageBundle content-language
|
|
null, // PageBundle content-language
|
|
'en-ca', // PageLanguage override
|
|
'en-ca', // explicit source
|
|
'en-ca' // expected source
|
|
];
|
|
}
|
|
|
|
/** @dataProvider provideSiteConfiguration */
|
|
public function testSiteConfiguration(
|
|
bool $isLanguageConversionEnabled,
|
|
bool $shouldParsoidBeUsed,
|
|
bool $shouldPageConfigFactoryBeUsed
|
|
) {
|
|
// Set expected language codes
|
|
$pageBundleLanguageCode = 'zh';
|
|
$titleLanguageCode = 'zh-hans';
|
|
$targetLanguageCode = 'zh-hans';
|
|
$sourceLanguageCode = null;
|
|
|
|
// Create mocks
|
|
$parsoidSettings = [];
|
|
|
|
$pageBundleMock = $this->getPageBundleMock( $pageBundleLanguageCode );
|
|
$languageVariantConverter = $this->getLanguageVariantConverter(
|
|
$shouldParsoidBeUsed,
|
|
$shouldPageConfigFactoryBeUsed,
|
|
$isLanguageConversionEnabled,
|
|
$pageBundleLanguageCode,
|
|
null,
|
|
$titleLanguageCode,
|
|
$targetLanguageCode,
|
|
$sourceLanguageCode,
|
|
$parsoidSettings
|
|
);
|
|
$languageVariantConverter->convertPageBundleVariant( $pageBundleMock, $targetLanguageCode );
|
|
}
|
|
|
|
public function provideSiteConfiguration() {
|
|
$isLanguageConversionEnabled = false;
|
|
$shouldParsoidBeUsed = false;
|
|
$shouldPageConfigFactoryBeUsed = false;
|
|
yield 'If language conversion is disabled, parsoid and page config factory should not be used' =>
|
|
[ $isLanguageConversionEnabled, $shouldParsoidBeUsed, $shouldPageConfigFactoryBeUsed ];
|
|
|
|
$isLanguageConversionEnabled = true;
|
|
$shouldParsoidBeUsed = true;
|
|
$shouldPageConfigFactoryBeUsed = true;
|
|
yield 'If language conversion is enabled, parsoid and page config factory should be used' =>
|
|
[ $isLanguageConversionEnabled, $shouldParsoidBeUsed, $shouldPageConfigFactoryBeUsed ];
|
|
}
|
|
|
|
/**
|
|
* @param bool $shouldParsoidBeUsed
|
|
* @param bool $shouldPageConfigFactoryBeUsed
|
|
* @param bool $isLanguageConversionEnabled
|
|
* @param string|null $pageBundleLanguageCode
|
|
* @param string|null $contentLanguageOverride
|
|
* @param string $titleLanguageCode
|
|
* @param string $targetLanguageCode
|
|
* @param string|null $sourceLanguageCode
|
|
* @param array $parsoidSettings
|
|
*
|
|
* @return LanguageVariantConverter
|
|
*/
|
|
private function getLanguageVariantConverter(
|
|
bool $shouldParsoidBeUsed,
|
|
bool $shouldPageConfigFactoryBeUsed,
|
|
bool $isLanguageConversionEnabled,
|
|
?string $pageBundleLanguageCode,
|
|
?string $contentLanguageOverride,
|
|
string $titleLanguageCode,
|
|
string $targetLanguageCode,
|
|
?string $sourceLanguageCode,
|
|
array $parsoidSettings
|
|
): LanguageVariantConverter {
|
|
// If Content language is set, use language from there,
|
|
// If PageBundle language code is set, use that
|
|
// Else, fallback to title page language
|
|
$pageLanguageCode = $contentLanguageOverride ?? $pageBundleLanguageCode ?? $titleLanguageCode;
|
|
// The page language code should not be a variant
|
|
$pageLanguageCode = preg_replace( '/-.*$/', '', $pageLanguageCode );
|
|
|
|
$shouldSiteConfigBeUsed = true;
|
|
$parsoidSettings = [];
|
|
$pageIdentityValue = new PageIdentityValue( 1, NS_MAIN, 'hello_world', PageIdentity::LOCAL );
|
|
|
|
// Create the necessary mocks
|
|
$pageConfigMock = $this->getPageConfigMock();
|
|
$pageConfigFactoryMock = $this->getPageConfigFactoryMock(
|
|
$shouldPageConfigFactoryBeUsed,
|
|
// Expected arguments to PageConfigFactory mock
|
|
[ $pageIdentityValue, null, null, null, $pageLanguageCode, $parsoidSettings ],
|
|
$pageConfigMock
|
|
);
|
|
$pageBundleMock = $this->getPageBundleMock( $pageBundleLanguageCode );
|
|
$siteConfigMock = $this->getSiteConfigMock(
|
|
$shouldSiteConfigBeUsed, $pageLanguageCode, $isLanguageConversionEnabled
|
|
);
|
|
$titleFactoryMock = $this->getTitleFactoryMock( $pageIdentityValue, $titleLanguageCode );
|
|
$languageFactoryMock = $this->getLanguageFactoryMock();
|
|
|
|
$parsoidMock = $this->getParsoidMock(
|
|
$shouldParsoidBeUsed,
|
|
[
|
|
$pageConfigMock,
|
|
'variant',
|
|
$pageBundleMock,
|
|
[ 'variant' => [ 'source' => $sourceLanguageCode, 'target' => $targetLanguageCode ] ]
|
|
]
|
|
);
|
|
|
|
$languageVariantConverter = new LanguageVariantConverter(
|
|
$pageIdentityValue,
|
|
$pageConfigFactoryMock,
|
|
$parsoidMock,
|
|
$parsoidSettings,
|
|
$siteConfigMock,
|
|
$titleFactoryMock,
|
|
$languageFactoryMock
|
|
);
|
|
|
|
if ( $contentLanguageOverride ) {
|
|
$languageVariantConverter->setPageLanguageOverride( $contentLanguageOverride );
|
|
}
|
|
|
|
return $languageVariantConverter;
|
|
}
|
|
|
|
// Mock methods follow
|
|
|
|
/**
|
|
* @param bool $shouldBeCalled
|
|
* @param array $arguments
|
|
* @param PageConfig $pageConfig
|
|
*
|
|
* @return MockObject|PageConfigFactory
|
|
*/
|
|
private function getPageConfigFactoryMock( bool $shouldBeCalled, array $arguments, PageConfig $pageConfig ) {
|
|
$mock = $this->createMock( PageConfigFactory::class );
|
|
|
|
if ( $shouldBeCalled ) {
|
|
$mock->expects( $this->once() )
|
|
->method( 'create' )
|
|
->with( ...$arguments )
|
|
->willReturn( $pageConfig );
|
|
} else {
|
|
$mock->expects( $this->never() )
|
|
->method( 'create' );
|
|
}
|
|
|
|
return $mock;
|
|
}
|
|
|
|
/**
|
|
* @param bool $shouldBeCalled
|
|
* @param array $arguments
|
|
*
|
|
* @return MockObject|Parsoid
|
|
*/
|
|
private function getParsoidMock( bool $shouldBeCalled, array $arguments ) {
|
|
$mock = $this->createMock( Parsoid::class );
|
|
if ( $shouldBeCalled ) {
|
|
$mock->expects( $this->once() )
|
|
->method( 'pb2pb' )
|
|
->with( ...$arguments );
|
|
} else {
|
|
$mock->expects( $this->never() )
|
|
->method( 'pb2pb' );
|
|
}
|
|
|
|
return $mock;
|
|
}
|
|
|
|
/**
|
|
* @param bool $shouldBeCalled
|
|
* @param string $baseLanguageCode
|
|
* @param bool $isLanguageConversionEnabled
|
|
*
|
|
* @return MockObject|SiteConfig
|
|
*/
|
|
private function getSiteConfigMock(
|
|
bool $shouldBeCalled,
|
|
string $baseLanguageCode,
|
|
bool $isLanguageConversionEnabled
|
|
) {
|
|
$mock = $this->createMock( SiteConfig::class );
|
|
if ( $shouldBeCalled ) {
|
|
$mock->expects( $this->once() )
|
|
->method( 'langConverterEnabledForLanguage' )
|
|
->with( $baseLanguageCode )
|
|
->willReturn( $isLanguageConversionEnabled );
|
|
} else {
|
|
$mock->expects( $this->never() )
|
|
->method( 'langConverterEnabledForLanguage' );
|
|
}
|
|
|
|
return $mock;
|
|
}
|
|
|
|
/**
|
|
* @param PageIdentity $pageIdentity
|
|
* @param string $languageCode
|
|
*
|
|
* @return MockObject|TitleFactory
|
|
*/
|
|
private function getTitleFactoryMock( PageIdentity $pageIdentity, string $languageCode ) {
|
|
$languageMock = $this->getLanguageMock( $languageCode );
|
|
|
|
$titleMock = $this->createMock( Title::class );
|
|
$titleMock->method( 'getPageLanguage' )
|
|
->willReturn( $languageMock );
|
|
|
|
$mock = $this->createMock( TitleFactory::class );
|
|
$mock->expects( $this->once() )
|
|
->method( 'castFromPageIdentity' )
|
|
->willReturn( $titleMock )
|
|
->with( $pageIdentity );
|
|
|
|
return $mock;
|
|
}
|
|
|
|
/**
|
|
* @return MockObject|LanguageFactory
|
|
*/
|
|
private function getLanguageFactoryMock() {
|
|
$mock = $this->createMock( LanguageFactory::class );
|
|
$mock->method( 'getLanguage' )
|
|
->willReturnCallback( function ( $code ) {
|
|
return $this->getLanguageMock( $code );
|
|
} );
|
|
$mock->method( 'getParentLanguage' )
|
|
->willReturnCallback( function ( $code ) {
|
|
$code = preg_replace( '/-.*$/', '', $code );
|
|
return $this->getLanguageMock( $code );
|
|
} );
|
|
|
|
return $mock;
|
|
}
|
|
|
|
/**
|
|
* @return MockObject|PageBundle
|
|
*/
|
|
private function getPageBundleMockWithoutLanguage() {
|
|
return $this->getPageBundleMock( null );
|
|
}
|
|
|
|
/**
|
|
* @param string|null $languageCode
|
|
*
|
|
* @return MockObject|PageBundle
|
|
*/
|
|
private function getPageBundleMock( ?string $languageCode ) {
|
|
$mock = $this->createMock( PageBundle::class );
|
|
$mock->headers = [
|
|
'content-language' => $languageCode
|
|
];
|
|
return $mock;
|
|
}
|
|
|
|
/**
|
|
* @return MockObject|PageConfig
|
|
*/
|
|
private function getPageConfigMock() {
|
|
$mock = $this->createNoOpMock( PageConfig::class, [ 'setVariant' ] );
|
|
return $mock;
|
|
}
|
|
|
|
/**
|
|
* @param string $languageCode
|
|
*
|
|
* @return MockObject|Language
|
|
*/
|
|
private function getLanguageMock( $languageCode ): Language {
|
|
$languageMock = $this->createMock( Language::class );
|
|
$languageMock->method( 'getCode' )
|
|
->willReturn( $languageCode );
|
|
|
|
return $languageMock;
|
|
}
|
|
}
|