2010-12-14 16:26:35 +00:00
|
|
|
<?php
|
|
|
|
|
|
2022-12-12 02:10:13 +00:00
|
|
|
use MediaWiki\Language\RawMessage;
|
2019-04-03 08:47:57 +00:00
|
|
|
use MediaWiki\Linker\LinkTarget;
|
2022-07-06 15:05:30 +00:00
|
|
|
use MediaWiki\MainConfigNames;
|
2021-09-17 15:56:30 +00:00
|
|
|
use MediaWiki\Page\PageIdentity;
|
2020-09-25 14:13:54 +00:00
|
|
|
use MediaWiki\Page\PageIdentityValue;
|
2021-05-05 00:03:26 +00:00
|
|
|
use MediaWiki\Tests\Unit\DummyServicesTrait;
|
2023-03-01 20:33:26 +00:00
|
|
|
use MediaWiki\Title\Title;
|
2021-09-07 18:11:26 +00:00
|
|
|
use Wikimedia\Assert\PreconditionException;
|
2018-06-11 06:55:11 +00:00
|
|
|
|
2012-09-05 16:54:15 +00:00
|
|
|
/**
|
2015-04-01 07:35:32 +00:00
|
|
|
* @group Database
|
2014-01-09 14:35:16 +00:00
|
|
|
* @group Title
|
2012-09-05 16:54:15 +00:00
|
|
|
*/
|
2020-06-30 15:09:24 +00:00
|
|
|
class TitleTest extends MediaWikiIntegrationTestCase {
|
2021-05-05 00:03:26 +00:00
|
|
|
use DummyServicesTrait;
|
2021-10-26 15:21:32 +00:00
|
|
|
use LinkCacheTestTrait;
|
2021-05-05 00:03:26 +00:00
|
|
|
|
2021-07-22 03:11:47 +00:00
|
|
|
protected function setUp(): void {
|
2012-10-08 10:56:20 +00:00
|
|
|
parent::setUp();
|
|
|
|
|
|
2021-09-07 18:11:26 +00:00
|
|
|
$this->mergeMwGlobalArrayValue(
|
|
|
|
|
'wgExtraNamespaces',
|
|
|
|
|
[
|
|
|
|
|
12302 => 'TEST-JS',
|
|
|
|
|
12303 => 'TEST-JS_TALK',
|
|
|
|
|
]
|
|
|
|
|
);
|
|
|
|
|
$this->mergeMwGlobalArrayValue(
|
|
|
|
|
'wgNamespaceContentModels',
|
|
|
|
|
[
|
|
|
|
|
12302 => CONTENT_MODEL_JAVASCRIPT,
|
|
|
|
|
]
|
|
|
|
|
);
|
|
|
|
|
|
2022-07-06 15:05:30 +00:00
|
|
|
$this->overrideConfigValues( [
|
|
|
|
|
MainConfigNames::AllowUserJs => false,
|
|
|
|
|
MainConfigNames::DefaultLanguageVariant => false,
|
|
|
|
|
MainConfigNames::MetaNamespace => 'Project',
|
|
|
|
|
MainConfigNames::Server => 'https://example.org',
|
|
|
|
|
MainConfigNames::CanonicalServer => 'https://example.org',
|
|
|
|
|
MainConfigNames::ScriptPath => '/w',
|
|
|
|
|
MainConfigNames::Script => '/w/index.php',
|
|
|
|
|
MainConfigNames::ArticlePath => '/wiki/$1',
|
2016-02-17 09:09:32 +00:00
|
|
|
] );
|
2016-03-09 16:47:58 +00:00
|
|
|
$this->setUserLang( 'en' );
|
2022-07-06 15:05:30 +00:00
|
|
|
$this->overrideConfigValue( MainConfigNames::LanguageCode, 'en' );
|
2021-05-05 00:03:26 +00:00
|
|
|
|
|
|
|
|
// For testSecureAndSplitValid, testSecureAndSplitInvalid
|
2022-07-06 15:05:30 +00:00
|
|
|
$this->overrideConfigValue( MainConfigNames::LocalInterwikis, [ 'localtestiw' ] );
|
2021-05-05 00:03:26 +00:00
|
|
|
|
|
|
|
|
// Define valid interwiki prefixes and their configuration
|
|
|
|
|
// DummyServicesTrait::getDummyInterwikiLookup
|
|
|
|
|
$interwikiLookup = $this->getDummyInterwikiLookup( [
|
|
|
|
|
// testSecureAndSplitValid, testSecureAndSplitInvalid
|
|
|
|
|
[ 'iw_prefix' => 'localtestiw', 'iw_url' => 'localtestiw' ],
|
|
|
|
|
[ 'iw_prefix' => 'remotetestiw', 'iw_url' => 'remotetestiw' ],
|
|
|
|
|
|
|
|
|
|
// testSubpages
|
|
|
|
|
'wiki',
|
|
|
|
|
|
|
|
|
|
// testIsValid
|
|
|
|
|
'wikipedia',
|
|
|
|
|
|
|
|
|
|
// testIsValidRedirectTarget
|
|
|
|
|
'acme',
|
|
|
|
|
|
|
|
|
|
// testGetFragmentForURL
|
|
|
|
|
[ 'iw_prefix' => 'de', 'iw_local' => 1 ],
|
|
|
|
|
[ 'iw_prefix' => 'zz', 'iw_local' => 0 ],
|
2021-09-07 18:11:26 +00:00
|
|
|
|
|
|
|
|
// Some tests use interwikis - define valid prefixes and their configuration
|
|
|
|
|
// DummyServicesTrait::getDummyInterwikiLookup
|
|
|
|
|
[ 'iw_prefix' => 'acme', 'iw_url' => 'https://acme.test/$1' ],
|
|
|
|
|
[ 'iw_prefix' => 'yy', 'iw_url' => 'https://yy.wiki.test/wiki/$1', 'iw_local' => true ]
|
2021-05-05 00:03:26 +00:00
|
|
|
] );
|
|
|
|
|
$this->setService( 'InterwikiLookup', $interwikiLookup );
|
2012-10-08 10:56:20 +00:00
|
|
|
}
|
|
|
|
|
|
2021-07-22 03:11:47 +00:00
|
|
|
protected function tearDown(): void {
|
2021-09-07 18:11:26 +00:00
|
|
|
Title::clearCaches();
|
2019-11-07 19:06:55 +00:00
|
|
|
parent::tearDown();
|
|
|
|
|
// delete dummy pages
|
|
|
|
|
$this->getNonexistingTestPage( 'UTest1' );
|
|
|
|
|
$this->getNonexistingTestPage( 'UTest2' );
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-07 18:11:26 +00:00
|
|
|
public static function provideInNamespace() {
|
|
|
|
|
return [
|
|
|
|
|
[ 'Main Page', NS_MAIN, true ],
|
|
|
|
|
[ 'Main Page', NS_TALK, false ],
|
|
|
|
|
[ 'Main Page', NS_USER, false ],
|
|
|
|
|
[ 'User:Foo', NS_USER, true ],
|
|
|
|
|
[ 'User:Foo', NS_USER_TALK, false ],
|
|
|
|
|
[ 'User:Foo', NS_TEMPLATE, false ],
|
|
|
|
|
[ 'User_talk:Foo', NS_USER_TALK, true ],
|
|
|
|
|
[ 'User_talk:Foo', NS_USER, false ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideInNamespace
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::inNamespace
|
2021-09-07 18:11:26 +00:00
|
|
|
*/
|
|
|
|
|
public function testInNamespace( $title, $ns, $expectedBool ) {
|
|
|
|
|
$title = Title::newFromText( $title );
|
|
|
|
|
$this->assertEquals( $expectedBool, $title->inNamespace( $ns ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::inNamespaces
|
2021-09-07 18:11:26 +00:00
|
|
|
*/
|
|
|
|
|
public function testInNamespaces() {
|
|
|
|
|
$mainpage = Title::newFromText( 'Main Page' );
|
|
|
|
|
$this->assertTrue( $mainpage->inNamespaces( NS_MAIN, NS_USER ) );
|
|
|
|
|
$this->assertTrue( $mainpage->inNamespaces( [ NS_MAIN, NS_USER ] ) );
|
|
|
|
|
$this->assertTrue( $mainpage->inNamespaces( [ NS_USER, NS_MAIN ] ) );
|
|
|
|
|
$this->assertFalse( $mainpage->inNamespaces( [ NS_PROJECT, NS_TEMPLATE ] ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static function provideHasSubjectNamespace() {
|
|
|
|
|
return [
|
|
|
|
|
[ 'Main Page', NS_MAIN, true ],
|
|
|
|
|
[ 'Main Page', NS_TALK, true ],
|
|
|
|
|
[ 'Main Page', NS_USER, false ],
|
|
|
|
|
[ 'User:Foo', NS_USER, true ],
|
|
|
|
|
[ 'User:Foo', NS_USER_TALK, true ],
|
|
|
|
|
[ 'User:Foo', NS_TEMPLATE, false ],
|
|
|
|
|
[ 'User_talk:Foo', NS_USER_TALK, true ],
|
|
|
|
|
[ 'User_talk:Foo', NS_USER, true ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideHasSubjectNamespace
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::hasSubjectNamespace
|
2021-09-07 18:11:26 +00:00
|
|
|
*/
|
|
|
|
|
public function testHasSubjectNamespace( $title, $ns, $expectedBool ) {
|
|
|
|
|
$title = Title::newFromText( $title );
|
|
|
|
|
$this->assertEquals( $expectedBool, $title->hasSubjectNamespace( $ns ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function dataGetContentModel() {
|
|
|
|
|
return [
|
|
|
|
|
[ 'Help:Foo', CONTENT_MODEL_WIKITEXT ],
|
|
|
|
|
[ 'Help:Foo.js', CONTENT_MODEL_WIKITEXT ],
|
|
|
|
|
[ 'Help:Foo/bar.js', CONTENT_MODEL_WIKITEXT ],
|
|
|
|
|
[ 'User:Foo', CONTENT_MODEL_WIKITEXT ],
|
|
|
|
|
[ 'User:Foo.js', CONTENT_MODEL_WIKITEXT ],
|
|
|
|
|
[ 'User:Foo/bar.js', CONTENT_MODEL_JAVASCRIPT ],
|
|
|
|
|
[ 'User:Foo/bar.css', CONTENT_MODEL_CSS ],
|
|
|
|
|
[ 'User talk:Foo/bar.css', CONTENT_MODEL_WIKITEXT ],
|
|
|
|
|
[ 'User:Foo/bar.js.xxx', CONTENT_MODEL_WIKITEXT ],
|
|
|
|
|
[ 'User:Foo/bar.xxx', CONTENT_MODEL_WIKITEXT ],
|
|
|
|
|
[ 'MediaWiki:Foo.js', CONTENT_MODEL_JAVASCRIPT ],
|
|
|
|
|
[ 'MediaWiki:Foo.css', CONTENT_MODEL_CSS ],
|
|
|
|
|
[ 'MediaWiki:Foo/bar.css', CONTENT_MODEL_CSS ],
|
|
|
|
|
[ 'MediaWiki:Foo.JS', CONTENT_MODEL_WIKITEXT ],
|
|
|
|
|
[ 'MediaWiki:Foo.CSS', CONTENT_MODEL_WIKITEXT ],
|
|
|
|
|
[ 'MediaWiki:Foo.css.xxx', CONTENT_MODEL_WIKITEXT ],
|
|
|
|
|
[ 'TEST-JS:Foo', CONTENT_MODEL_JAVASCRIPT ],
|
|
|
|
|
[ 'TEST-JS:Foo.js', CONTENT_MODEL_JAVASCRIPT ],
|
|
|
|
|
[ 'TEST-JS:Foo/bar.js', CONTENT_MODEL_JAVASCRIPT ],
|
|
|
|
|
[ 'TEST-JS_TALK:Foo.js', CONTENT_MODEL_WIKITEXT ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider dataGetContentModel
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getContentModel
|
2021-09-07 18:11:26 +00:00
|
|
|
*/
|
|
|
|
|
public function testGetContentModel( $title, $expectedModelId ) {
|
|
|
|
|
$title = Title::newFromText( $title );
|
|
|
|
|
$this->assertEquals( $expectedModelId, $title->getContentModel() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider dataGetContentModel
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::hasContentModel
|
2021-09-07 18:11:26 +00:00
|
|
|
*/
|
|
|
|
|
public function testHasContentModel( $title, $expectedModelId ) {
|
|
|
|
|
$title = Title::newFromText( $title );
|
|
|
|
|
$this->assertTrue( $title->hasContentModel( $expectedModelId ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static function provideIsSiteConfigPage() {
|
|
|
|
|
return [
|
|
|
|
|
[ 'Help:Foo', false ],
|
|
|
|
|
[ 'Help:Foo.js', false ],
|
|
|
|
|
[ 'Help:Foo/bar.js', false ],
|
|
|
|
|
[ 'User:Foo', false ],
|
|
|
|
|
[ 'User:Foo.js', false ],
|
|
|
|
|
[ 'User:Foo/bar.js', false ],
|
|
|
|
|
[ 'User:Foo/bar.json', false ],
|
|
|
|
|
[ 'User:Foo/bar.css', false ],
|
|
|
|
|
[ 'User:Foo/bar.JS', false ],
|
|
|
|
|
[ 'User:Foo/bar.JSON', false ],
|
|
|
|
|
[ 'User:Foo/bar.CSS', false ],
|
|
|
|
|
[ 'User talk:Foo/bar.css', false ],
|
|
|
|
|
[ 'User:Foo/bar.js.xxx', false ],
|
|
|
|
|
[ 'User:Foo/bar.xxx', false ],
|
|
|
|
|
[ 'MediaWiki:Foo.js', 'javascript' ],
|
|
|
|
|
[ 'MediaWiki:Foo.json', 'json' ],
|
|
|
|
|
[ 'MediaWiki:Foo.css', 'css' ],
|
|
|
|
|
[ 'MediaWiki:Foo.JS', false ],
|
|
|
|
|
[ 'MediaWiki:Foo.JSON', false ],
|
|
|
|
|
[ 'MediaWiki:Foo.CSS', false ],
|
|
|
|
|
[ 'MediaWiki:Foo/bar.css', 'css' ],
|
|
|
|
|
[ 'MediaWiki:Foo.css.xxx', false ],
|
|
|
|
|
[ 'TEST-JS:Foo', false ],
|
|
|
|
|
[ 'TEST-JS:Foo.js', false ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideIsSiteConfigPage
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::isSiteConfigPage
|
|
|
|
|
* @covers MediaWiki\Title\Title::isSiteJsConfigPage
|
|
|
|
|
* @covers MediaWiki\Title\Title::isSiteJsonConfigPage
|
|
|
|
|
* @covers MediaWiki\Title\Title::isSiteCssConfigPage
|
2021-09-07 18:11:26 +00:00
|
|
|
*/
|
|
|
|
|
public function testSiteConfigPage( $title, $expected ) {
|
|
|
|
|
$title = Title::newFromText( $title );
|
|
|
|
|
|
|
|
|
|
// $expected is either false or the relevant type ('javascript', 'json', 'css')
|
|
|
|
|
$this->assertSame(
|
|
|
|
|
$expected !== false,
|
|
|
|
|
$title->isSiteConfigPage()
|
|
|
|
|
);
|
|
|
|
|
$this->assertSame(
|
|
|
|
|
$expected === 'javascript',
|
|
|
|
|
$title->isSiteJsConfigPage()
|
|
|
|
|
);
|
|
|
|
|
$this->assertSame(
|
|
|
|
|
$expected === 'json',
|
|
|
|
|
$title->isSiteJsonConfigPage()
|
|
|
|
|
);
|
|
|
|
|
$this->assertSame(
|
|
|
|
|
$expected === 'css',
|
|
|
|
|
$title->isSiteCssConfigPage()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static function provideIsUserConfigPage() {
|
|
|
|
|
return [
|
|
|
|
|
[ 'Help:Foo', false ],
|
|
|
|
|
[ 'Help:Foo.js', false ],
|
|
|
|
|
[ 'Help:Foo/bar.js', false ],
|
|
|
|
|
[ 'User:Foo', false ],
|
|
|
|
|
[ 'User:Foo.js', false ],
|
|
|
|
|
[ 'User:Foo/bar.js', 'javascript' ],
|
|
|
|
|
[ 'User:Foo/bar.JS', false ],
|
|
|
|
|
[ 'User:Foo/bar.json', 'json' ],
|
|
|
|
|
[ 'User:Foo/bar.JSON', false ],
|
|
|
|
|
[ 'User:Foo/bar.css', 'css' ],
|
|
|
|
|
[ 'User:Foo/bar.CSS', false ],
|
|
|
|
|
[ 'User talk:Foo/bar.css', false ],
|
|
|
|
|
[ 'User:Foo/bar.js.xxx', false ],
|
|
|
|
|
[ 'User:Foo/bar.xxx', false ],
|
|
|
|
|
[ 'MediaWiki:Foo.js', false ],
|
|
|
|
|
[ 'MediaWiki:Foo.json', false ],
|
|
|
|
|
[ 'MediaWiki:Foo.css', false ],
|
|
|
|
|
[ 'MediaWiki:Foo.JS', false ],
|
|
|
|
|
[ 'MediaWiki:Foo.JSON', false ],
|
|
|
|
|
[ 'MediaWiki:Foo.CSS', false ],
|
|
|
|
|
[ 'MediaWiki:Foo.css.xxx', false ],
|
|
|
|
|
[ 'TEST-JS:Foo', false ],
|
|
|
|
|
[ 'TEST-JS:Foo.js', false ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideIsUserConfigPage
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::isUserConfigPage
|
|
|
|
|
* @covers MediaWiki\Title\Title::isUserJsConfigPage
|
|
|
|
|
* @covers MediaWiki\Title\Title::isUserJsonConfigPage
|
|
|
|
|
* @covers MediaWiki\Title\Title::isUserCssConfigPage
|
2021-09-07 18:11:26 +00:00
|
|
|
*/
|
|
|
|
|
public function testIsUserConfigPage( $title, $expected ) {
|
|
|
|
|
$title = Title::newFromText( $title );
|
|
|
|
|
|
|
|
|
|
// $expected is either false or the relevant type ('javascript', 'json', 'css')
|
|
|
|
|
$this->assertSame(
|
|
|
|
|
$expected !== false,
|
|
|
|
|
$title->isUserConfigPage()
|
|
|
|
|
);
|
|
|
|
|
$this->assertSame(
|
|
|
|
|
$expected === 'javascript',
|
|
|
|
|
$title->isUserJsConfigPage()
|
|
|
|
|
);
|
|
|
|
|
$this->assertSame(
|
|
|
|
|
$expected === 'json',
|
|
|
|
|
$title->isUserJsonConfigPage()
|
|
|
|
|
);
|
|
|
|
|
$this->assertSame(
|
|
|
|
|
$expected === 'css',
|
|
|
|
|
$title->isUserCssConfigPage()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static function provideIsWikitextPage() {
|
|
|
|
|
return [
|
|
|
|
|
[ 'Help:Foo', true ],
|
|
|
|
|
[ 'Help:Foo.js', true ],
|
|
|
|
|
[ 'Help:Foo/bar.js', true ],
|
|
|
|
|
[ 'User:Foo', true ],
|
|
|
|
|
[ 'User:Foo.js', true ],
|
|
|
|
|
[ 'User:Foo/bar.js', false ],
|
|
|
|
|
[ 'User:Foo/bar.json', false ],
|
|
|
|
|
[ 'User:Foo/bar.css', false ],
|
|
|
|
|
[ 'User talk:Foo/bar.css', true ],
|
|
|
|
|
[ 'User:Foo/bar.js.xxx', true ],
|
|
|
|
|
[ 'User:Foo/bar.xxx', true ],
|
|
|
|
|
[ 'MediaWiki:Foo.js', false ],
|
|
|
|
|
[ 'User:Foo/bar.JS', true ],
|
|
|
|
|
[ 'User:Foo/bar.JSON', true ],
|
|
|
|
|
[ 'User:Foo/bar.CSS', true ],
|
|
|
|
|
[ 'MediaWiki:Foo.json', false ],
|
|
|
|
|
[ 'MediaWiki:Foo.css', false ],
|
|
|
|
|
[ 'MediaWiki:Foo.JS', true ],
|
|
|
|
|
[ 'MediaWiki:Foo.JSON', true ],
|
|
|
|
|
[ 'MediaWiki:Foo.CSS', true ],
|
|
|
|
|
[ 'MediaWiki:Foo.css.xxx', true ],
|
|
|
|
|
[ 'TEST-JS:Foo', false ],
|
|
|
|
|
[ 'TEST-JS:Foo.js', false ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideIsWikitextPage
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::isWikitextPage
|
2021-09-07 18:11:26 +00:00
|
|
|
*/
|
|
|
|
|
public function testIsWikitextPage( $title, $expectedBool ) {
|
|
|
|
|
$title = Title::newFromText( $title );
|
|
|
|
|
$this->assertEquals( $expectedBool, $title->isWikitextPage() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static function provideGetOtherPage() {
|
|
|
|
|
return [
|
|
|
|
|
[ 'Main Page', 'Talk:Main Page' ],
|
|
|
|
|
[ 'Talk:Main Page', 'Main Page' ],
|
|
|
|
|
[ 'Help:Main Page', 'Help talk:Main Page' ],
|
|
|
|
|
[ 'Help talk:Main Page', 'Help:Main Page' ],
|
|
|
|
|
[ 'Special:FooBar', null ],
|
|
|
|
|
[ 'Media:File.jpg', null ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideGetOtherpage
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getOtherPage
|
2021-09-07 18:11:26 +00:00
|
|
|
*
|
|
|
|
|
* @param string $text
|
|
|
|
|
* @param string|null $expected
|
|
|
|
|
*/
|
|
|
|
|
public function testGetOtherPage( $text, $expected ) {
|
|
|
|
|
if ( $expected === null ) {
|
|
|
|
|
$this->expectException( MWException::class );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$title = Title::newFromText( $text );
|
|
|
|
|
$this->assertEquals( $expected, $title->getOtherPage()->getPrefixedText() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::clearCaches
|
2021-09-07 18:11:26 +00:00
|
|
|
*/
|
|
|
|
|
public function testClearCaches() {
|
2021-10-26 15:21:32 +00:00
|
|
|
$linkCache = $this->getServiceContainer()->getLinkCache();
|
2021-09-07 18:11:26 +00:00
|
|
|
|
|
|
|
|
$title1 = Title::newFromText( 'Foo' );
|
2021-10-26 15:21:32 +00:00
|
|
|
$this->addGoodLinkObject( 23, $title1 );
|
2021-09-07 18:11:26 +00:00
|
|
|
|
|
|
|
|
Title::clearCaches();
|
|
|
|
|
|
|
|
|
|
$title2 = Title::newFromText( 'Foo' );
|
|
|
|
|
$this->assertNotSame( $title1, $title2, 'title cache should be empty' );
|
|
|
|
|
$this->assertSame( 0, $linkCache->getGoodLinkID( 'Foo' ), 'link cache should be empty' );
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-22 13:32:59 +00:00
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getFieldFromPageStore
|
2021-11-22 13:32:59 +00:00
|
|
|
*/
|
|
|
|
|
public function testUseCaches() {
|
|
|
|
|
$title1 = Title::makeTitle( NS_MAIN, __METHOD__ . '998724352' );
|
|
|
|
|
$this->addGoodLinkObject( 23, $title1, 7, 0, 42 );
|
|
|
|
|
|
|
|
|
|
// Ensure that getLatestRevID uses the LinkCache even after
|
|
|
|
|
// the article ID is known (T296063#7520023).
|
|
|
|
|
$this->assertSame( 23, $title1->getArticleID() );
|
|
|
|
|
$this->assertSame( 42, $title1->getLatestRevID() );
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-23 11:36:19 +00:00
|
|
|
public static function provideGetLinkURL() {
|
2021-09-07 18:11:26 +00:00
|
|
|
yield 'Simple' => [
|
|
|
|
|
'/wiki/Goats',
|
|
|
|
|
NS_MAIN,
|
|
|
|
|
'Goats'
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
yield 'Fragment' => [
|
|
|
|
|
'/wiki/Goats#Goatificatiön',
|
|
|
|
|
NS_MAIN,
|
|
|
|
|
'Goats',
|
|
|
|
|
'Goatificatiön'
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
yield 'Fragment only (query is ignored)' => [
|
|
|
|
|
'#Goatificatiön',
|
|
|
|
|
NS_MAIN,
|
|
|
|
|
'',
|
|
|
|
|
'Goatificatiön',
|
|
|
|
|
'',
|
|
|
|
|
[
|
|
|
|
|
'a' => 1,
|
|
|
|
|
]
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
yield 'Unknown interwiki with fragment' => [
|
|
|
|
|
'https://xx.wiki.test/wiki/xyzzy:Goats#Goatificatiön',
|
|
|
|
|
NS_MAIN,
|
|
|
|
|
'Goats',
|
|
|
|
|
'Goatificatiön',
|
|
|
|
|
'xyzzy'
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
yield 'Interwiki with fragment' => [
|
|
|
|
|
'https://acme.test/Goats#Goatificati.C3.B6n',
|
|
|
|
|
NS_MAIN,
|
|
|
|
|
'Goats',
|
|
|
|
|
'Goatificatiön',
|
|
|
|
|
'acme'
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
yield 'Interwiki with query' => [
|
|
|
|
|
'https://acme.test/Goats?a=1&b=blank+blank#Goatificati.C3.B6n',
|
|
|
|
|
NS_MAIN,
|
|
|
|
|
'Goats',
|
|
|
|
|
'Goatificatiön',
|
|
|
|
|
'acme',
|
|
|
|
|
[
|
|
|
|
|
'a' => 1,
|
|
|
|
|
'b' => 'blank blank'
|
|
|
|
|
]
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
yield 'Local interwiki with fragment' => [
|
|
|
|
|
'https://yy.wiki.test/wiki/Goats#Goatificatiön',
|
|
|
|
|
NS_MAIN,
|
|
|
|
|
'Goats',
|
|
|
|
|
'Goatificatiön',
|
|
|
|
|
'yy'
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideGetLinkURL
|
|
|
|
|
*
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getLinkURL
|
|
|
|
|
* @covers MediaWiki\Title\Title::getFullURL
|
|
|
|
|
* @covers MediaWiki\Title\Title::getLocalURL
|
|
|
|
|
* @covers MediaWiki\Title\Title::getFragmentForURL
|
2021-09-07 18:11:26 +00:00
|
|
|
*/
|
|
|
|
|
public function testGetLinkURL(
|
|
|
|
|
$expected,
|
|
|
|
|
$ns,
|
|
|
|
|
$title,
|
|
|
|
|
$fragment = '',
|
|
|
|
|
$interwiki = '',
|
|
|
|
|
$query = '',
|
|
|
|
|
$query2 = false,
|
|
|
|
|
$proto = false
|
|
|
|
|
) {
|
2022-07-06 15:05:30 +00:00
|
|
|
$this->overrideConfigValues( [
|
|
|
|
|
MainConfigNames::Server => 'https://xx.wiki.test',
|
|
|
|
|
MainConfigNames::ArticlePath => '/wiki/$1',
|
|
|
|
|
MainConfigNames::ExternalInterwikiFragmentMode => 'legacy',
|
|
|
|
|
MainConfigNames::FragmentMode => [ 'html5', 'legacy' ]
|
2021-09-07 18:11:26 +00:00
|
|
|
] );
|
|
|
|
|
|
|
|
|
|
$title = Title::makeTitle( $ns, $title, $fragment, $interwiki );
|
|
|
|
|
$this->assertSame( $expected, $title->getLinkURL( $query, $query2, $proto ) );
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-23 11:36:19 +00:00
|
|
|
public static function provideProperPage() {
|
2021-09-07 18:11:26 +00:00
|
|
|
return [
|
|
|
|
|
[ NS_MAIN, 'Test' ],
|
|
|
|
|
[ NS_MAIN, 'User' ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideProperPage
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::toPageIdentity
|
2021-09-07 18:11:26 +00:00
|
|
|
*/
|
|
|
|
|
public function testToPageIdentity( $ns, $text ) {
|
|
|
|
|
$title = Title::makeTitle( $ns, $text );
|
|
|
|
|
|
|
|
|
|
$page = $title->toPageIdentity();
|
|
|
|
|
|
|
|
|
|
$this->assertNotSame( $title, $page );
|
|
|
|
|
$this->assertSame( $title->getId(), $page->getId() );
|
|
|
|
|
$this->assertSame( $title->getNamespace(), $page->getNamespace() );
|
|
|
|
|
$this->assertSame( $title->getDBkey(), $page->getDBkey() );
|
|
|
|
|
$this->assertSame( $title->getWikiId(), $page->getWikiId() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideProperPage
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::toPageRecord
|
2021-09-07 18:11:26 +00:00
|
|
|
*/
|
|
|
|
|
public function testToPageRecord( $ns, $text ) {
|
|
|
|
|
$title = Title::makeTitle( $ns, $text );
|
|
|
|
|
$wikiPage = $this->getExistingTestPage( $title );
|
|
|
|
|
|
|
|
|
|
$record = $title->toPageRecord();
|
|
|
|
|
|
|
|
|
|
$this->assertNotSame( $title, $record );
|
|
|
|
|
$this->assertNotSame( $title, $wikiPage );
|
|
|
|
|
|
|
|
|
|
$this->assertSame( $title->getId(), $record->getId() );
|
|
|
|
|
$this->assertSame( $title->getNamespace(), $record->getNamespace() );
|
|
|
|
|
$this->assertSame( $title->getDBkey(), $record->getDBkey() );
|
|
|
|
|
$this->assertSame( $title->getWikiId(), $record->getWikiId() );
|
|
|
|
|
|
|
|
|
|
$this->assertSame( $title->getLatestRevID(), $record->getLatest() );
|
|
|
|
|
$this->assertSame( MWTimestamp::convert( TS_MW, $title->getTouched() ), $record->getTouched() );
|
|
|
|
|
$this->assertSame( $title->isNewPage(), $record->isNew() );
|
|
|
|
|
$this->assertSame( $title->isRedirect(), $record->isRedirect() );
|
2021-06-09 21:01:30 +00:00
|
|
|
$this->assertSame( $title->getTouched(), $record->getTouched() );
|
2021-09-07 18:11:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideImproperPage
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::toPageRecord
|
2021-09-07 18:11:26 +00:00
|
|
|
*/
|
|
|
|
|
public function testToPageRecord_fail( $ns, $text, $fragment = '', $interwiki = '' ) {
|
|
|
|
|
$title = Title::makeTitle( $ns, $text, $fragment, $interwiki );
|
|
|
|
|
|
|
|
|
|
$this->expectException( PreconditionException::class );
|
|
|
|
|
$title->toPageRecord();
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-23 11:36:19 +00:00
|
|
|
public static function provideImproperPage() {
|
2021-09-07 18:11:26 +00:00
|
|
|
return [
|
|
|
|
|
[ NS_MAIN, '' ],
|
|
|
|
|
[ NS_MAIN, '<>' ],
|
|
|
|
|
[ NS_MAIN, '|' ],
|
|
|
|
|
[ NS_MAIN, '#' ],
|
|
|
|
|
[ NS_PROJECT, '#test' ],
|
|
|
|
|
[ NS_MAIN, '', 'test', 'acme' ],
|
|
|
|
|
[ NS_MAIN, ' Test' ],
|
|
|
|
|
[ NS_MAIN, '_Test' ],
|
|
|
|
|
[ NS_MAIN, 'Test ' ],
|
|
|
|
|
[ NS_MAIN, 'Test_' ],
|
|
|
|
|
[ NS_MAIN, "Test\nthis" ],
|
|
|
|
|
[ NS_MAIN, "Test\tthis" ],
|
|
|
|
|
[ -33, 'Test' ],
|
|
|
|
|
[ 77663399, 'Test' ],
|
|
|
|
|
|
|
|
|
|
// Valid but can't exist
|
|
|
|
|
[ NS_MAIN, '', 'test' ],
|
|
|
|
|
[ NS_SPECIAL, 'Test' ],
|
|
|
|
|
[ NS_MAIN, 'Test', '', 'acme' ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideImproperPage
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getId
|
2021-09-07 18:11:26 +00:00
|
|
|
*/
|
|
|
|
|
public function testGetId_fail( $ns, $text, $fragment = '', $interwiki = '' ) {
|
|
|
|
|
$title = Title::makeTitle( $ns, $text, $fragment, $interwiki );
|
|
|
|
|
|
|
|
|
|
$this->expectException( PreconditionException::class );
|
|
|
|
|
$title->getId();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideImproperPage
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getId
|
2021-09-07 18:11:26 +00:00
|
|
|
*/
|
|
|
|
|
public function testGetId_fragment() {
|
|
|
|
|
$title = Title::makeTitle( NS_MAIN, 'Test', 'References' );
|
|
|
|
|
|
|
|
|
|
// should not throw
|
|
|
|
|
$this->assertIsInt( $title->getId() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideImproperPage
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::toPageIdentity
|
2021-09-07 18:11:26 +00:00
|
|
|
*/
|
|
|
|
|
public function testToPageIdentity_fail( $ns, $text, $fragment = '', $interwiki = '' ) {
|
|
|
|
|
$title = Title::makeTitle( $ns, $text, $fragment, $interwiki );
|
|
|
|
|
|
|
|
|
|
$this->expectException( PreconditionException::class );
|
|
|
|
|
$title->toPageIdentity();
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-23 11:36:19 +00:00
|
|
|
public static function provideMakeTitle() {
|
2021-09-07 18:11:26 +00:00
|
|
|
yield 'main namespace' => [ 'Foo', NS_MAIN, 'Foo' ];
|
|
|
|
|
yield 'user namespace' => [ 'User:Foo', NS_USER, 'Foo' ];
|
|
|
|
|
yield 'fragment' => [ 'Foo#Section', NS_MAIN, 'Foo', 'Section' ];
|
|
|
|
|
yield 'only fragment' => [ '#Section', NS_MAIN, '', 'Section' ];
|
|
|
|
|
yield 'interwiki' => [ 'acme:Foo', NS_MAIN, 'Foo', '', 'acme' ];
|
|
|
|
|
yield 'normalized underscores' => [ 'Foo Bar', NS_MAIN, 'Foo_Bar' ];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideMakeTitle
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::makeTitle
|
2021-09-07 18:11:26 +00:00
|
|
|
*/
|
|
|
|
|
public function testMakeTitle( $expected, $ns, $text, $fragment = '', $interwiki = '' ) {
|
|
|
|
|
$title = Title::makeTitle( $ns, $text, $fragment, $interwiki );
|
|
|
|
|
|
|
|
|
|
$this->assertTrue( $title->isValid() );
|
|
|
|
|
$this->assertSame( $expected, $title->getFullText() );
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-23 11:36:19 +00:00
|
|
|
public static function provideMakeTitle_invalid() {
|
2021-09-07 18:11:26 +00:00
|
|
|
yield 'bad namespace' => [ 'Special:Badtitle/NS-1234:Foo', -1234, 'Foo' ];
|
|
|
|
|
yield 'lower case' => [ 'User:foo', NS_USER, 'foo' ];
|
|
|
|
|
yield 'empty' => [ '', NS_MAIN, '' ];
|
|
|
|
|
yield 'bad character' => [ 'Foo|Bar', NS_MAIN, 'Foo|Bar' ];
|
2022-07-30 04:56:20 +00:00
|
|
|
yield 'bad interwiki' => [ 'qwerty:Foo', NS_MAIN, 'Foo', '', 'qwerty' ];
|
2021-09-07 18:11:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideMakeTitle_invalid
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::makeTitle
|
2021-09-07 18:11:26 +00:00
|
|
|
*/
|
|
|
|
|
public function testMakeTitle_invalid( $expected, $ns, $text, $fragment = '', $interwiki = '' ) {
|
|
|
|
|
$title = Title::makeTitle( $ns, $text, $fragment, $interwiki );
|
|
|
|
|
|
|
|
|
|
$this->assertFalse( $title->isValid() );
|
|
|
|
|
$this->assertSame( $expected, $title->getFullText() );
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-23 11:36:19 +00:00
|
|
|
public static function provideMakeName() {
|
2023-02-15 20:08:23 +00:00
|
|
|
yield 'main namespace' => [ 'Foo', NS_MAIN, 'Foo' ];
|
|
|
|
|
yield 'user namespace' => [ 'User:Foo', NS_USER, 'Foo' ];
|
|
|
|
|
yield 'fragment' => [ 'Foo#Section', NS_MAIN, 'Foo', 'Section' ];
|
|
|
|
|
yield 'only fragment' => [ '#Section', NS_MAIN, '', 'Section' ];
|
|
|
|
|
yield 'interwiki' => [ 'acme:Foo', NS_MAIN, 'Foo', '', 'acme' ];
|
|
|
|
|
yield 'bad namespace' => [ 'Special:Badtitle/NS-1234:Foo', -1234, 'Foo' ];
|
|
|
|
|
yield 'lower case' => [ 'User:foo', NS_USER, 'foo' ];
|
|
|
|
|
yield 'empty' => [ '', NS_MAIN, '' ];
|
|
|
|
|
yield 'bad character' => [ 'Foo|Bar', NS_MAIN, 'Foo|Bar' ];
|
|
|
|
|
yield 'bad interwiki' => [ 'qwerty:Foo', NS_MAIN, 'Foo', '', 'qwerty' ];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideMakeName
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::makeName
|
2023-02-15 20:08:23 +00:00
|
|
|
*/
|
|
|
|
|
public function testMakeName( $expected, $ns, $text, $fragment = '', $interwiki = '' ) {
|
|
|
|
|
$titleName = Title::makeName( $ns, $text, $fragment, $interwiki );
|
|
|
|
|
|
|
|
|
|
$this->assertSame( $expected, $titleName );
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-23 11:36:19 +00:00
|
|
|
public static function provideMakeTitleSafe() {
|
2021-09-07 18:11:26 +00:00
|
|
|
yield 'main namespace' => [ 'Foo', NS_MAIN, 'Foo' ];
|
|
|
|
|
yield 'user namespace' => [ 'User:Foo', NS_USER, 'Foo' ];
|
|
|
|
|
yield 'fragment' => [ 'Foo#Section', NS_MAIN, 'Foo', 'Section' ];
|
|
|
|
|
yield 'only fragment' => [ '#Section', NS_MAIN, '', 'Section' ];
|
|
|
|
|
yield 'interwiki' => [ 'acme:Foo', NS_MAIN, 'Foo', '', 'acme' ];
|
|
|
|
|
|
|
|
|
|
// Normalize
|
|
|
|
|
yield 'normalized underscores' => [ 'Foo Bar', NS_MAIN, 'Foo_Bar' ];
|
|
|
|
|
yield 'lower case' => [ 'User:Foo', NS_USER, 'foo' ];
|
|
|
|
|
|
|
|
|
|
// Bad interwiki becomes part of the title text. Is this intentional?
|
|
|
|
|
yield 'bad interwiki' => [ 'Qwerty:Foo', NS_MAIN, 'Foo', '', 'qwerty' ];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideMakeTitleSafe
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::makeTitleSafe
|
2021-09-07 18:11:26 +00:00
|
|
|
*/
|
|
|
|
|
public function testMakeTitleSafe( $expected, $ns, $text, $fragment = '', $interwiki = '' ) {
|
|
|
|
|
$title = Title::makeTitleSafe( $ns, $text, $fragment, $interwiki );
|
|
|
|
|
|
|
|
|
|
$this->assertTrue( $title->isValid() );
|
|
|
|
|
$this->assertSame( $expected, $title->getFullText() );
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-23 11:36:19 +00:00
|
|
|
public static function provideMakeTitleSafe_invalid() {
|
2021-09-07 18:11:26 +00:00
|
|
|
yield 'bad namespace' => [ -1234, 'Foo' ];
|
|
|
|
|
yield 'empty' => [ '', NS_MAIN, '' ];
|
|
|
|
|
yield 'bad character' => [ NS_MAIN, 'Foo|Bar' ];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideMakeTitleSafe_invalid
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::makeTitleSafe
|
2021-09-07 18:11:26 +00:00
|
|
|
*/
|
|
|
|
|
public function testMakeTitleSafe_invalid( $ns, $text, $fragment = '', $interwiki = '' ) {
|
|
|
|
|
$title = Title::makeTitleSafe( $ns, $text, $fragment, $interwiki );
|
|
|
|
|
|
|
|
|
|
$this->assertNull( $title );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getContentModel
|
|
|
|
|
* @covers MediaWiki\Title\Title::setContentModel
|
|
|
|
|
* @covers MediaWiki\Title\Title::uncache
|
2021-09-07 18:11:26 +00:00
|
|
|
*/
|
|
|
|
|
public function testSetContentModel() {
|
|
|
|
|
// NOTE: must use newFromText to test behavior of internal instance cache (T281337)
|
|
|
|
|
$title = Title::newFromText( 'Foo' );
|
|
|
|
|
|
|
|
|
|
$title->setContentModel( CONTENT_MODEL_UNKNOWN );
|
|
|
|
|
$this->assertSame( CONTENT_MODEL_UNKNOWN, $title->getContentModel() );
|
|
|
|
|
|
|
|
|
|
// Ensure that the instance we get back from newFromText isn't the modified one.
|
|
|
|
|
$title = Title::newFromText( 'Foo' );
|
|
|
|
|
$this->assertNotSame( CONTENT_MODEL_UNKNOWN, $title->getContentModel() );
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-07 19:03:13 +00:00
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::newFromID
|
|
|
|
|
* @covers MediaWiki\Title\Title::newFromIDs
|
|
|
|
|
* @covers MediaWiki\Title\Title::newFromRow
|
2021-03-07 19:03:13 +00:00
|
|
|
*/
|
|
|
|
|
public function testNewFromIds() {
|
|
|
|
|
// First id
|
|
|
|
|
$existingPage1 = $this->getExistingTestPage( 'UTest1' );
|
|
|
|
|
$existingTitle1 = $existingPage1->getTitle();
|
|
|
|
|
$existingId1 = $existingTitle1->getId();
|
|
|
|
|
|
2021-11-21 16:23:11 +00:00
|
|
|
$this->assertGreaterThan( 0, $existingId1, 'Existing test page should have a positive id' );
|
2021-03-07 19:03:13 +00:00
|
|
|
|
|
|
|
|
$newFromId1 = Title::newFromID( $existingId1 );
|
|
|
|
|
$this->assertInstanceOf( Title::class, $newFromId1, 'newFromID returns a title for an existing id' );
|
|
|
|
|
$this->assertTrue(
|
|
|
|
|
$newFromId1->equals( $existingTitle1 ),
|
|
|
|
|
'newFromID returns the correct title'
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Second id
|
|
|
|
|
$existingPage2 = $this->getExistingTestPage( 'UTest2' );
|
|
|
|
|
$existingTitle2 = $existingPage2->getTitle();
|
|
|
|
|
$existingId2 = $existingTitle2->getId();
|
|
|
|
|
|
2021-11-21 16:23:11 +00:00
|
|
|
$this->assertGreaterThan( 0, $existingId2, 'Existing test page should have a positive id' );
|
2021-03-07 19:03:13 +00:00
|
|
|
|
|
|
|
|
$newFromId2 = Title::newFromID( $existingId2 );
|
|
|
|
|
$this->assertInstanceOf( Title::class, $newFromId2, 'newFromID returns a title for an existing id' );
|
|
|
|
|
$this->assertTrue(
|
|
|
|
|
$newFromId2->equals( $existingTitle2 ),
|
|
|
|
|
'newFromID returns the correct title'
|
|
|
|
|
);
|
|
|
|
|
|
2021-11-15 22:30:11 +00:00
|
|
|
$this->filterDeprecated( '/newFromIDs/' );
|
2021-03-07 19:03:13 +00:00
|
|
|
// newFromIDs using both
|
|
|
|
|
$titles = Title::newFromIDs( [ $existingId1, $existingId2 ] );
|
|
|
|
|
$this->assertCount( 2, $titles );
|
|
|
|
|
$this->assertTrue(
|
|
|
|
|
$titles[0]->equals( $existingTitle1 ) &&
|
|
|
|
|
$titles[1]->equals( $existingTitle2 ),
|
|
|
|
|
'newFromIDs returns an array that matches the correct titles'
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// newFromIds early return for an empty array of ids
|
|
|
|
|
$this->assertSame( [], Title::newFromIDs( [] ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::newFromID
|
2021-03-07 19:03:13 +00:00
|
|
|
*/
|
|
|
|
|
public function testNewFromMissingId() {
|
|
|
|
|
// Testing return of null for an id that does not exist
|
|
|
|
|
$maxPageId = (int)$this->db->selectField(
|
|
|
|
|
'page',
|
|
|
|
|
'max(page_id)',
|
|
|
|
|
'',
|
|
|
|
|
__METHOD__
|
|
|
|
|
);
|
2022-12-04 19:09:28 +00:00
|
|
|
$res = Title::newFromID( $maxPageId + 1 );
|
2021-03-07 19:03:13 +00:00
|
|
|
$this->assertNull( $res, 'newFromID returns null for missing ids' );
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-18 01:28:26 +00:00
|
|
|
public static function provideValidSecureAndSplit() {
|
2016-02-17 09:09:32 +00:00
|
|
|
return [
|
|
|
|
|
[ 'Sandbox' ],
|
|
|
|
|
[ 'A "B"' ],
|
|
|
|
|
[ 'A \'B\'' ],
|
|
|
|
|
[ '.com' ],
|
|
|
|
|
[ '~' ],
|
|
|
|
|
[ '#' ],
|
|
|
|
|
[ '"' ],
|
|
|
|
|
[ '\'' ],
|
|
|
|
|
[ 'Talk:Sandbox' ],
|
|
|
|
|
[ 'Talk:Foo:Sandbox' ],
|
|
|
|
|
[ 'File:Example.svg' ],
|
|
|
|
|
[ 'File_talk:Example.svg' ],
|
|
|
|
|
[ 'Foo/.../Sandbox' ],
|
|
|
|
|
[ 'Sandbox/...' ],
|
|
|
|
|
[ 'A~~' ],
|
|
|
|
|
[ ':A' ],
|
mw.Title: Rewrite from scratch (porting logic from Title.php)
Changes:
* Add support for fragments.
* Use wgLegalTitleChars instead of the old clean() method
that stripped out characters instead of throwing an exception.
* Implemented various other parts of Title.php to make it more
strict like Title.php. It is still slightly looser, but it
now takes care of the following that Title.php did already:
- Directory patterns ("../" etc.)
- Extra initial colons
- Titles in NS_TALK that don't round-trip to NS_MAIN
- 3 or more consecutive tildes
- Limited title size (255 bytes)
* Extracted parsing logic into a private static #parse method
and introduced mw.Title.newFromText (a constructor that returns
null|Title instead of throwing an exception).
* Extended test suite to cover the added features and fixed bugs.
* Since the PHP test suite was lacking these, added them there
as well.
Bug fixes:
* Fragments are now excluded from the title instead of causing
the input to be invalid or malformed (e.g. "Foo#bar" was being
normalised to "Foo_bar").
* ".com" now parses and round-trips properly. The extension and
rest of title are still separated, but only at the very end
after all other processing, so though title cannot be empty,
since we only do a lazy split afterwards, it will split into
title="", ext="com" internally and join back together when
needed (bug 38081).
* "Example.js " (trailing space after extension) was previously
incorrectly parsed as title=Example.js,ext=null.
* "Foo bar" (multiple consecutive spaces) was transformed
into 1 space correctly, but "Foo___bar" was not. This has been
fixed to match the PHP implementation (it merges underscores
and whitespace of any kind).
Clean up:
* Removed various redundant private helper methods.
* Removed fixNsId as getNsIdByName uses wgNamespaceIds which
always yields a valid value. The fixNsId was verifying
something that was already valid.
* Yoda conditional in Title.php, got rid of.
* Use newFromText in jquery.byteLimit.test. It was previously
using a very basic invalid test (=== '') and no try-catch.
Since we're getting more strict, typing 'User:' results in
an invalid title, which should result in the same behaviour
as it previously did for the lazy === '' check.
Bug: 38081
Change-Id: Ief1c11dabadc2f822065c40be91e04d655933e4f
2013-07-31 22:12:16 +00:00
|
|
|
// Length is 256 total, but only title part matters
|
2016-02-17 09:09:32 +00:00
|
|
|
[ 'Category:' . str_repeat( 'x', 248 ) ],
|
|
|
|
|
[ str_repeat( 'x', 252 ) ],
|
2014-01-10 20:40:25 +00:00
|
|
|
// interwiki prefix
|
2016-02-17 09:09:32 +00:00
|
|
|
[ 'localtestiw: #anchor' ],
|
|
|
|
|
[ 'localtestiw:' ],
|
|
|
|
|
[ 'localtestiw:foo' ],
|
|
|
|
|
[ 'localtestiw: foo # anchor' ],
|
|
|
|
|
[ 'localtestiw: Talk: Sandbox # anchor' ],
|
|
|
|
|
[ 'remotetestiw:' ],
|
|
|
|
|
[ 'remotetestiw: Talk: # anchor' ],
|
|
|
|
|
[ 'remotetestiw: #bar' ],
|
|
|
|
|
[ 'remotetestiw: Talk:' ],
|
|
|
|
|
[ 'remotetestiw: Talk: Foo' ],
|
|
|
|
|
[ 'localtestiw:remotetestiw:' ],
|
|
|
|
|
[ 'localtestiw:remotetestiw:foo' ]
|
|
|
|
|
];
|
2014-09-05 17:52:31 +00:00
|
|
|
}
|
mw.Title: Rewrite from scratch (porting logic from Title.php)
Changes:
* Add support for fragments.
* Use wgLegalTitleChars instead of the old clean() method
that stripped out characters instead of throwing an exception.
* Implemented various other parts of Title.php to make it more
strict like Title.php. It is still slightly looser, but it
now takes care of the following that Title.php did already:
- Directory patterns ("../" etc.)
- Extra initial colons
- Titles in NS_TALK that don't round-trip to NS_MAIN
- 3 or more consecutive tildes
- Limited title size (255 bytes)
* Extracted parsing logic into a private static #parse method
and introduced mw.Title.newFromText (a constructor that returns
null|Title instead of throwing an exception).
* Extended test suite to cover the added features and fixed bugs.
* Since the PHP test suite was lacking these, added them there
as well.
Bug fixes:
* Fragments are now excluded from the title instead of causing
the input to be invalid or malformed (e.g. "Foo#bar" was being
normalised to "Foo_bar").
* ".com" now parses and round-trips properly. The extension and
rest of title are still separated, but only at the very end
after all other processing, so though title cannot be empty,
since we only do a lazy split afterwards, it will split into
title="", ext="com" internally and join back together when
needed (bug 38081).
* "Example.js " (trailing space after extension) was previously
incorrectly parsed as title=Example.js,ext=null.
* "Foo bar" (multiple consecutive spaces) was transformed
into 1 space correctly, but "Foo___bar" was not. This has been
fixed to match the PHP implementation (it merges underscores
and whitespace of any kind).
Clean up:
* Removed various redundant private helper methods.
* Removed fixNsId as getNsIdByName uses wgNamespaceIds which
always yields a valid value. The fixNsId was verifying
something that was already valid.
* Yoda conditional in Title.php, got rid of.
* Use newFromText in jquery.byteLimit.test. It was previously
using a very basic invalid test (=== '') and no try-catch.
Since we're getting more strict, typing 'User:' results in
an invalid title, which should result in the same behaviour
as it previously did for the lazy === '' check.
Bug: 38081
Change-Id: Ief1c11dabadc2f822065c40be91e04d655933e4f
2013-07-31 22:12:16 +00:00
|
|
|
|
2014-09-18 01:28:26 +00:00
|
|
|
public static function provideInvalidSecureAndSplit() {
|
2016-02-17 09:09:32 +00:00
|
|
|
return [
|
|
|
|
|
[ '', 'title-invalid-empty' ],
|
|
|
|
|
[ ':', 'title-invalid-empty' ],
|
|
|
|
|
[ '__ __', 'title-invalid-empty' ],
|
|
|
|
|
[ ' __ ', 'title-invalid-empty' ],
|
mw.Title: Rewrite from scratch (porting logic from Title.php)
Changes:
* Add support for fragments.
* Use wgLegalTitleChars instead of the old clean() method
that stripped out characters instead of throwing an exception.
* Implemented various other parts of Title.php to make it more
strict like Title.php. It is still slightly looser, but it
now takes care of the following that Title.php did already:
- Directory patterns ("../" etc.)
- Extra initial colons
- Titles in NS_TALK that don't round-trip to NS_MAIN
- 3 or more consecutive tildes
- Limited title size (255 bytes)
* Extracted parsing logic into a private static #parse method
and introduced mw.Title.newFromText (a constructor that returns
null|Title instead of throwing an exception).
* Extended test suite to cover the added features and fixed bugs.
* Since the PHP test suite was lacking these, added them there
as well.
Bug fixes:
* Fragments are now excluded from the title instead of causing
the input to be invalid or malformed (e.g. "Foo#bar" was being
normalised to "Foo_bar").
* ".com" now parses and round-trips properly. The extension and
rest of title are still separated, but only at the very end
after all other processing, so though title cannot be empty,
since we only do a lazy split afterwards, it will split into
title="", ext="com" internally and join back together when
needed (bug 38081).
* "Example.js " (trailing space after extension) was previously
incorrectly parsed as title=Example.js,ext=null.
* "Foo bar" (multiple consecutive spaces) was transformed
into 1 space correctly, but "Foo___bar" was not. This has been
fixed to match the PHP implementation (it merges underscores
and whitespace of any kind).
Clean up:
* Removed various redundant private helper methods.
* Removed fixNsId as getNsIdByName uses wgNamespaceIds which
always yields a valid value. The fixNsId was verifying
something that was already valid.
* Yoda conditional in Title.php, got rid of.
* Use newFromText in jquery.byteLimit.test. It was previously
using a very basic invalid test (=== '') and no try-catch.
Since we're getting more strict, typing 'User:' results in
an invalid title, which should result in the same behaviour
as it previously did for the lazy === '' check.
Bug: 38081
Change-Id: Ief1c11dabadc2f822065c40be91e04d655933e4f
2013-07-31 22:12:16 +00:00
|
|
|
// Bad characters forbidden regardless of wgLegalTitleChars
|
2016-02-17 09:09:32 +00:00
|
|
|
[ 'A [ B', 'title-invalid-characters' ],
|
|
|
|
|
[ 'A ] B', 'title-invalid-characters' ],
|
|
|
|
|
[ 'A { B', 'title-invalid-characters' ],
|
|
|
|
|
[ 'A } B', 'title-invalid-characters' ],
|
|
|
|
|
[ 'A < B', 'title-invalid-characters' ],
|
|
|
|
|
[ 'A > B', 'title-invalid-characters' ],
|
|
|
|
|
[ 'A | B', 'title-invalid-characters' ],
|
2016-08-24 19:33:45 +00:00
|
|
|
[ "A \t B", 'title-invalid-characters' ],
|
|
|
|
|
[ "A \n B", 'title-invalid-characters' ],
|
mw.Title: Rewrite from scratch (porting logic from Title.php)
Changes:
* Add support for fragments.
* Use wgLegalTitleChars instead of the old clean() method
that stripped out characters instead of throwing an exception.
* Implemented various other parts of Title.php to make it more
strict like Title.php. It is still slightly looser, but it
now takes care of the following that Title.php did already:
- Directory patterns ("../" etc.)
- Extra initial colons
- Titles in NS_TALK that don't round-trip to NS_MAIN
- 3 or more consecutive tildes
- Limited title size (255 bytes)
* Extracted parsing logic into a private static #parse method
and introduced mw.Title.newFromText (a constructor that returns
null|Title instead of throwing an exception).
* Extended test suite to cover the added features and fixed bugs.
* Since the PHP test suite was lacking these, added them there
as well.
Bug fixes:
* Fragments are now excluded from the title instead of causing
the input to be invalid or malformed (e.g. "Foo#bar" was being
normalised to "Foo_bar").
* ".com" now parses and round-trips properly. The extension and
rest of title are still separated, but only at the very end
after all other processing, so though title cannot be empty,
since we only do a lazy split afterwards, it will split into
title="", ext="com" internally and join back together when
needed (bug 38081).
* "Example.js " (trailing space after extension) was previously
incorrectly parsed as title=Example.js,ext=null.
* "Foo bar" (multiple consecutive spaces) was transformed
into 1 space correctly, but "Foo___bar" was not. This has been
fixed to match the PHP implementation (it merges underscores
and whitespace of any kind).
Clean up:
* Removed various redundant private helper methods.
* Removed fixNsId as getNsIdByName uses wgNamespaceIds which
always yields a valid value. The fixNsId was verifying
something that was already valid.
* Yoda conditional in Title.php, got rid of.
* Use newFromText in jquery.byteLimit.test. It was previously
using a very basic invalid test (=== '') and no try-catch.
Since we're getting more strict, typing 'User:' results in
an invalid title, which should result in the same behaviour
as it previously did for the lazy === '' check.
Bug: 38081
Change-Id: Ief1c11dabadc2f822065c40be91e04d655933e4f
2013-07-31 22:12:16 +00:00
|
|
|
// URL encoding
|
2016-02-17 09:09:32 +00:00
|
|
|
[ 'A%20B', 'title-invalid-characters' ],
|
|
|
|
|
[ 'A%23B', 'title-invalid-characters' ],
|
|
|
|
|
[ 'A%2523B', 'title-invalid-characters' ],
|
mw.Title: Rewrite from scratch (porting logic from Title.php)
Changes:
* Add support for fragments.
* Use wgLegalTitleChars instead of the old clean() method
that stripped out characters instead of throwing an exception.
* Implemented various other parts of Title.php to make it more
strict like Title.php. It is still slightly looser, but it
now takes care of the following that Title.php did already:
- Directory patterns ("../" etc.)
- Extra initial colons
- Titles in NS_TALK that don't round-trip to NS_MAIN
- 3 or more consecutive tildes
- Limited title size (255 bytes)
* Extracted parsing logic into a private static #parse method
and introduced mw.Title.newFromText (a constructor that returns
null|Title instead of throwing an exception).
* Extended test suite to cover the added features and fixed bugs.
* Since the PHP test suite was lacking these, added them there
as well.
Bug fixes:
* Fragments are now excluded from the title instead of causing
the input to be invalid or malformed (e.g. "Foo#bar" was being
normalised to "Foo_bar").
* ".com" now parses and round-trips properly. The extension and
rest of title are still separated, but only at the very end
after all other processing, so though title cannot be empty,
since we only do a lazy split afterwards, it will split into
title="", ext="com" internally and join back together when
needed (bug 38081).
* "Example.js " (trailing space after extension) was previously
incorrectly parsed as title=Example.js,ext=null.
* "Foo bar" (multiple consecutive spaces) was transformed
into 1 space correctly, but "Foo___bar" was not. This has been
fixed to match the PHP implementation (it merges underscores
and whitespace of any kind).
Clean up:
* Removed various redundant private helper methods.
* Removed fixNsId as getNsIdByName uses wgNamespaceIds which
always yields a valid value. The fixNsId was verifying
something that was already valid.
* Yoda conditional in Title.php, got rid of.
* Use newFromText in jquery.byteLimit.test. It was previously
using a very basic invalid test (=== '') and no try-catch.
Since we're getting more strict, typing 'User:' results in
an invalid title, which should result in the same behaviour
as it previously did for the lazy === '' check.
Bug: 38081
Change-Id: Ief1c11dabadc2f822065c40be91e04d655933e4f
2013-07-31 22:12:16 +00:00
|
|
|
// XML/HTML character entity references
|
|
|
|
|
// Note: Commented out because they are not marked invalid by the PHP test as
|
|
|
|
|
// Title::newFromText runs Sanitizer::decodeCharReferencesAndNormalize first.
|
2015-09-11 13:44:59 +00:00
|
|
|
// 'A é B',
|
mw.Title: Rewrite from scratch (porting logic from Title.php)
Changes:
* Add support for fragments.
* Use wgLegalTitleChars instead of the old clean() method
that stripped out characters instead of throwing an exception.
* Implemented various other parts of Title.php to make it more
strict like Title.php. It is still slightly looser, but it
now takes care of the following that Title.php did already:
- Directory patterns ("../" etc.)
- Extra initial colons
- Titles in NS_TALK that don't round-trip to NS_MAIN
- 3 or more consecutive tildes
- Limited title size (255 bytes)
* Extracted parsing logic into a private static #parse method
and introduced mw.Title.newFromText (a constructor that returns
null|Title instead of throwing an exception).
* Extended test suite to cover the added features and fixed bugs.
* Since the PHP test suite was lacking these, added them there
as well.
Bug fixes:
* Fragments are now excluded from the title instead of causing
the input to be invalid or malformed (e.g. "Foo#bar" was being
normalised to "Foo_bar").
* ".com" now parses and round-trips properly. The extension and
rest of title are still separated, but only at the very end
after all other processing, so though title cannot be empty,
since we only do a lazy split afterwards, it will split into
title="", ext="com" internally and join back together when
needed (bug 38081).
* "Example.js " (trailing space after extension) was previously
incorrectly parsed as title=Example.js,ext=null.
* "Foo bar" (multiple consecutive spaces) was transformed
into 1 space correctly, but "Foo___bar" was not. This has been
fixed to match the PHP implementation (it merges underscores
and whitespace of any kind).
Clean up:
* Removed various redundant private helper methods.
* Removed fixNsId as getNsIdByName uses wgNamespaceIds which
always yields a valid value. The fixNsId was verifying
something that was already valid.
* Yoda conditional in Title.php, got rid of.
* Use newFromText in jquery.byteLimit.test. It was previously
using a very basic invalid test (=== '') and no try-catch.
Since we're getting more strict, typing 'User:' results in
an invalid title, which should result in the same behaviour
as it previously did for the lazy === '' check.
Bug: 38081
Change-Id: Ief1c11dabadc2f822065c40be91e04d655933e4f
2013-07-31 22:12:16 +00:00
|
|
|
// Subject of NS_TALK does not roundtrip to NS_MAIN
|
2016-02-17 09:09:32 +00:00
|
|
|
[ 'Talk:File:Example.svg', 'title-invalid-talk-namespace' ],
|
mw.Title: Rewrite from scratch (porting logic from Title.php)
Changes:
* Add support for fragments.
* Use wgLegalTitleChars instead of the old clean() method
that stripped out characters instead of throwing an exception.
* Implemented various other parts of Title.php to make it more
strict like Title.php. It is still slightly looser, but it
now takes care of the following that Title.php did already:
- Directory patterns ("../" etc.)
- Extra initial colons
- Titles in NS_TALK that don't round-trip to NS_MAIN
- 3 or more consecutive tildes
- Limited title size (255 bytes)
* Extracted parsing logic into a private static #parse method
and introduced mw.Title.newFromText (a constructor that returns
null|Title instead of throwing an exception).
* Extended test suite to cover the added features and fixed bugs.
* Since the PHP test suite was lacking these, added them there
as well.
Bug fixes:
* Fragments are now excluded from the title instead of causing
the input to be invalid or malformed (e.g. "Foo#bar" was being
normalised to "Foo_bar").
* ".com" now parses and round-trips properly. The extension and
rest of title are still separated, but only at the very end
after all other processing, so though title cannot be empty,
since we only do a lazy split afterwards, it will split into
title="", ext="com" internally and join back together when
needed (bug 38081).
* "Example.js " (trailing space after extension) was previously
incorrectly parsed as title=Example.js,ext=null.
* "Foo bar" (multiple consecutive spaces) was transformed
into 1 space correctly, but "Foo___bar" was not. This has been
fixed to match the PHP implementation (it merges underscores
and whitespace of any kind).
Clean up:
* Removed various redundant private helper methods.
* Removed fixNsId as getNsIdByName uses wgNamespaceIds which
always yields a valid value. The fixNsId was verifying
something that was already valid.
* Yoda conditional in Title.php, got rid of.
* Use newFromText in jquery.byteLimit.test. It was previously
using a very basic invalid test (=== '') and no try-catch.
Since we're getting more strict, typing 'User:' results in
an invalid title, which should result in the same behaviour
as it previously did for the lazy === '' check.
Bug: 38081
Change-Id: Ief1c11dabadc2f822065c40be91e04d655933e4f
2013-07-31 22:12:16 +00:00
|
|
|
// Directory navigation
|
2016-02-17 09:09:32 +00:00
|
|
|
[ '.', 'title-invalid-relative' ],
|
|
|
|
|
[ '..', 'title-invalid-relative' ],
|
|
|
|
|
[ './Sandbox', 'title-invalid-relative' ],
|
|
|
|
|
[ '../Sandbox', 'title-invalid-relative' ],
|
|
|
|
|
[ 'Foo/./Sandbox', 'title-invalid-relative' ],
|
|
|
|
|
[ 'Foo/../Sandbox', 'title-invalid-relative' ],
|
|
|
|
|
[ 'Sandbox/.', 'title-invalid-relative' ],
|
|
|
|
|
[ 'Sandbox/..', 'title-invalid-relative' ],
|
mw.Title: Rewrite from scratch (porting logic from Title.php)
Changes:
* Add support for fragments.
* Use wgLegalTitleChars instead of the old clean() method
that stripped out characters instead of throwing an exception.
* Implemented various other parts of Title.php to make it more
strict like Title.php. It is still slightly looser, but it
now takes care of the following that Title.php did already:
- Directory patterns ("../" etc.)
- Extra initial colons
- Titles in NS_TALK that don't round-trip to NS_MAIN
- 3 or more consecutive tildes
- Limited title size (255 bytes)
* Extracted parsing logic into a private static #parse method
and introduced mw.Title.newFromText (a constructor that returns
null|Title instead of throwing an exception).
* Extended test suite to cover the added features and fixed bugs.
* Since the PHP test suite was lacking these, added them there
as well.
Bug fixes:
* Fragments are now excluded from the title instead of causing
the input to be invalid or malformed (e.g. "Foo#bar" was being
normalised to "Foo_bar").
* ".com" now parses and round-trips properly. The extension and
rest of title are still separated, but only at the very end
after all other processing, so though title cannot be empty,
since we only do a lazy split afterwards, it will split into
title="", ext="com" internally and join back together when
needed (bug 38081).
* "Example.js " (trailing space after extension) was previously
incorrectly parsed as title=Example.js,ext=null.
* "Foo bar" (multiple consecutive spaces) was transformed
into 1 space correctly, but "Foo___bar" was not. This has been
fixed to match the PHP implementation (it merges underscores
and whitespace of any kind).
Clean up:
* Removed various redundant private helper methods.
* Removed fixNsId as getNsIdByName uses wgNamespaceIds which
always yields a valid value. The fixNsId was verifying
something that was already valid.
* Yoda conditional in Title.php, got rid of.
* Use newFromText in jquery.byteLimit.test. It was previously
using a very basic invalid test (=== '') and no try-catch.
Since we're getting more strict, typing 'User:' results in
an invalid title, which should result in the same behaviour
as it previously did for the lazy === '' check.
Bug: 38081
Change-Id: Ief1c11dabadc2f822065c40be91e04d655933e4f
2013-07-31 22:12:16 +00:00
|
|
|
// Tilde
|
2016-02-17 09:09:32 +00:00
|
|
|
[ 'A ~~~ Name', 'title-invalid-magic-tilde' ],
|
|
|
|
|
[ 'A ~~~~ Signature', 'title-invalid-magic-tilde' ],
|
|
|
|
|
[ 'A ~~~~~ Timestamp', 'title-invalid-magic-tilde' ],
|
2015-04-25 22:43:37 +00:00
|
|
|
// Length
|
2016-02-17 09:09:32 +00:00
|
|
|
[ str_repeat( 'x', 256 ), 'title-invalid-too-long' ],
|
mw.Title: Rewrite from scratch (porting logic from Title.php)
Changes:
* Add support for fragments.
* Use wgLegalTitleChars instead of the old clean() method
that stripped out characters instead of throwing an exception.
* Implemented various other parts of Title.php to make it more
strict like Title.php. It is still slightly looser, but it
now takes care of the following that Title.php did already:
- Directory patterns ("../" etc.)
- Extra initial colons
- Titles in NS_TALK that don't round-trip to NS_MAIN
- 3 or more consecutive tildes
- Limited title size (255 bytes)
* Extracted parsing logic into a private static #parse method
and introduced mw.Title.newFromText (a constructor that returns
null|Title instead of throwing an exception).
* Extended test suite to cover the added features and fixed bugs.
* Since the PHP test suite was lacking these, added them there
as well.
Bug fixes:
* Fragments are now excluded from the title instead of causing
the input to be invalid or malformed (e.g. "Foo#bar" was being
normalised to "Foo_bar").
* ".com" now parses and round-trips properly. The extension and
rest of title are still separated, but only at the very end
after all other processing, so though title cannot be empty,
since we only do a lazy split afterwards, it will split into
title="", ext="com" internally and join back together when
needed (bug 38081).
* "Example.js " (trailing space after extension) was previously
incorrectly parsed as title=Example.js,ext=null.
* "Foo bar" (multiple consecutive spaces) was transformed
into 1 space correctly, but "Foo___bar" was not. This has been
fixed to match the PHP implementation (it merges underscores
and whitespace of any kind).
Clean up:
* Removed various redundant private helper methods.
* Removed fixNsId as getNsIdByName uses wgNamespaceIds which
always yields a valid value. The fixNsId was verifying
something that was already valid.
* Yoda conditional in Title.php, got rid of.
* Use newFromText in jquery.byteLimit.test. It was previously
using a very basic invalid test (=== '') and no try-catch.
Since we're getting more strict, typing 'User:' results in
an invalid title, which should result in the same behaviour
as it previously did for the lazy === '' check.
Bug: 38081
Change-Id: Ief1c11dabadc2f822065c40be91e04d655933e4f
2013-07-31 22:12:16 +00:00
|
|
|
// Namespace prefix without actual title
|
2016-02-17 09:09:32 +00:00
|
|
|
[ 'Talk:', 'title-invalid-empty' ],
|
|
|
|
|
[ 'Talk:#', 'title-invalid-empty' ],
|
|
|
|
|
[ 'Category: ', 'title-invalid-empty' ],
|
|
|
|
|
[ 'Category: #bar', 'title-invalid-empty' ],
|
2014-01-10 20:40:25 +00:00
|
|
|
// interwiki prefix
|
2016-02-17 09:09:32 +00:00
|
|
|
[ 'localtestiw: Talk: # anchor', 'title-invalid-empty' ],
|
|
|
|
|
[ 'localtestiw: Talk:', 'title-invalid-empty' ]
|
|
|
|
|
];
|
2014-09-05 17:52:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* See also mediawiki.Title.test.js
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::secureAndSplit
|
2014-09-05 17:52:31 +00:00
|
|
|
* @dataProvider provideValidSecureAndSplit
|
|
|
|
|
* @note This mainly tests MediaWikiTitleCodec::parseTitle().
|
|
|
|
|
*/
|
|
|
|
|
public function testSecureAndSplitValid( $text ) {
|
2018-01-13 00:02:09 +00:00
|
|
|
$this->assertInstanceOf( Title::class, Title::newFromText( $text ), "Valid: $text" );
|
2014-09-05 17:52:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* See also mediawiki.Title.test.js
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::secureAndSplit
|
2014-09-05 17:52:31 +00:00
|
|
|
* @dataProvider provideInvalidSecureAndSplit
|
|
|
|
|
* @note This mainly tests MediaWikiTitleCodec::parseTitle().
|
|
|
|
|
*/
|
2015-04-25 22:43:37 +00:00
|
|
|
public function testSecureAndSplitInvalid( $text, $expectedErrorMessage ) {
|
|
|
|
|
try {
|
|
|
|
|
Title::newFromTextThrow( $text ); // should throw
|
2020-12-23 10:03:34 +00:00
|
|
|
$this->fail( "Title::newFromTextThrow should have thrown with $text" );
|
2015-04-25 22:43:37 +00:00
|
|
|
} catch ( MalformedTitleException $ex ) {
|
|
|
|
|
$this->assertEquals( $expectedErrorMessage, $ex->getErrorMessage(), "Invalid: $text" );
|
|
|
|
|
}
|
mw.Title: Rewrite from scratch (porting logic from Title.php)
Changes:
* Add support for fragments.
* Use wgLegalTitleChars instead of the old clean() method
that stripped out characters instead of throwing an exception.
* Implemented various other parts of Title.php to make it more
strict like Title.php. It is still slightly looser, but it
now takes care of the following that Title.php did already:
- Directory patterns ("../" etc.)
- Extra initial colons
- Titles in NS_TALK that don't round-trip to NS_MAIN
- 3 or more consecutive tildes
- Limited title size (255 bytes)
* Extracted parsing logic into a private static #parse method
and introduced mw.Title.newFromText (a constructor that returns
null|Title instead of throwing an exception).
* Extended test suite to cover the added features and fixed bugs.
* Since the PHP test suite was lacking these, added them there
as well.
Bug fixes:
* Fragments are now excluded from the title instead of causing
the input to be invalid or malformed (e.g. "Foo#bar" was being
normalised to "Foo_bar").
* ".com" now parses and round-trips properly. The extension and
rest of title are still separated, but only at the very end
after all other processing, so though title cannot be empty,
since we only do a lazy split afterwards, it will split into
title="", ext="com" internally and join back together when
needed (bug 38081).
* "Example.js " (trailing space after extension) was previously
incorrectly parsed as title=Example.js,ext=null.
* "Foo bar" (multiple consecutive spaces) was transformed
into 1 space correctly, but "Foo___bar" was not. This has been
fixed to match the PHP implementation (it merges underscores
and whitespace of any kind).
Clean up:
* Removed various redundant private helper methods.
* Removed fixNsId as getNsIdByName uses wgNamespaceIds which
always yields a valid value. The fixNsId was verifying
something that was already valid.
* Yoda conditional in Title.php, got rid of.
* Use newFromText in jquery.byteLimit.test. It was previously
using a very basic invalid test (=== '') and no try-catch.
Since we're getting more strict, typing 'User:' results in
an invalid title, which should result in the same behaviour
as it previously did for the lazy === '' check.
Bug: 38081
Change-Id: Ief1c11dabadc2f822065c40be91e04d655933e4f
2013-07-31 22:12:16 +00:00
|
|
|
}
|
|
|
|
|
|
2021-09-07 18:45:21 +00:00
|
|
|
public static function provideSpecialNamesWithAndWithoutParameter() {
|
|
|
|
|
return [
|
|
|
|
|
[ 'Special:Version', null ],
|
|
|
|
|
[ 'Special:Version/', '' ],
|
|
|
|
|
[ 'Special:Version/param', 'param' ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-22 21:35:24 +00:00
|
|
|
/**
|
2014-08-28 18:38:18 +00:00
|
|
|
* @dataProvider provideSpecialNamesWithAndWithoutParameter
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::fixSpecialName
|
2011-09-22 21:35:24 +00:00
|
|
|
*/
|
2014-08-28 18:38:18 +00:00
|
|
|
public function testFixSpecialNameRetainsParameter( $text, $expectedParam ) {
|
2011-09-22 21:35:24 +00:00
|
|
|
$title = Title::newFromText( $text );
|
|
|
|
|
$fixed = $title->fixSpecialName();
|
2013-03-22 07:39:02 +00:00
|
|
|
$stuff = explode( '/', $fixed->getDBkey(), 2 );
|
2011-09-22 21:35:24 +00:00
|
|
|
if ( count( $stuff ) == 2 ) {
|
|
|
|
|
$par = $stuff[1];
|
|
|
|
|
} else {
|
|
|
|
|
$par = null;
|
|
|
|
|
}
|
2014-04-24 12:50:36 +00:00
|
|
|
$this->assertEquals(
|
|
|
|
|
$expectedParam,
|
|
|
|
|
$par,
|
2017-02-20 23:45:58 +00:00
|
|
|
"T33100 regression check: Title->fixSpecialName() should preserve parameter"
|
2014-04-24 12:50:36 +00:00
|
|
|
);
|
2011-09-22 21:35:24 +00:00
|
|
|
}
|
|
|
|
|
|
2013-10-21 21:09:13 +00:00
|
|
|
public function flattenErrorsArray( $errors ) {
|
2016-02-17 09:09:32 +00:00
|
|
|
$result = [];
|
2011-09-29 18:35:34 +00:00
|
|
|
foreach ( $errors as $error ) {
|
|
|
|
|
$result[] = $error[0];
|
|
|
|
|
}
|
2013-04-26 12:00:22 +00:00
|
|
|
|
2011-09-29 18:35:34 +00:00
|
|
|
return $result;
|
|
|
|
|
}
|
2013-02-14 11:36:35 +00:00
|
|
|
|
2013-10-21 21:09:13 +00:00
|
|
|
public static function provideGetPageViewLanguage() {
|
2012-06-02 18:07:46 +00:00
|
|
|
# Format:
|
|
|
|
|
# - expected
|
|
|
|
|
# - Title name
|
2018-07-29 12:24:54 +00:00
|
|
|
# - content language (expected in most cases)
|
2012-06-02 18:07:46 +00:00
|
|
|
# - wgLang (on some specific pages)
|
|
|
|
|
# - wgDefaultLanguageVariant
|
2016-02-17 09:09:32 +00:00
|
|
|
return [
|
|
|
|
|
[ 'fr', 'Help:I_need_somebody', 'fr', 'fr', false ],
|
|
|
|
|
[ 'es', 'Help:I_need_somebody', 'es', 'zh-tw', false ],
|
|
|
|
|
[ 'zh', 'Help:I_need_somebody', 'zh', 'zh-tw', false ],
|
|
|
|
|
|
|
|
|
|
[ 'es', 'Help:I_need_somebody', 'es', 'zh-tw', 'zh-cn' ],
|
|
|
|
|
[ 'es', 'MediaWiki:About', 'es', 'zh-tw', 'zh-cn' ],
|
|
|
|
|
[ 'es', 'MediaWiki:About/', 'es', 'zh-tw', 'zh-cn' ],
|
|
|
|
|
[ 'de', 'MediaWiki:About/de', 'es', 'zh-tw', 'zh-cn' ],
|
|
|
|
|
[ 'en', 'MediaWiki:Common.js', 'es', 'zh-tw', 'zh-cn' ],
|
|
|
|
|
[ 'en', 'MediaWiki:Common.css', 'es', 'zh-tw', 'zh-cn' ],
|
|
|
|
|
[ 'en', 'User:JohnDoe/Common.js', 'es', 'zh-tw', 'zh-cn' ],
|
|
|
|
|
[ 'en', 'User:JohnDoe/Monobook.css', 'es', 'zh-tw', 'zh-cn' ],
|
|
|
|
|
|
|
|
|
|
[ 'zh-cn', 'Help:I_need_somebody', 'zh', 'zh-tw', 'zh-cn' ],
|
|
|
|
|
[ 'zh', 'MediaWiki:About', 'zh', 'zh-tw', 'zh-cn' ],
|
|
|
|
|
[ 'zh', 'MediaWiki:About/', 'zh', 'zh-tw', 'zh-cn' ],
|
|
|
|
|
[ 'de', 'MediaWiki:About/de', 'zh', 'zh-tw', 'zh-cn' ],
|
|
|
|
|
[ 'zh-cn', 'MediaWiki:About/zh-cn', 'zh', 'zh-tw', 'zh-cn' ],
|
|
|
|
|
[ 'zh-tw', 'MediaWiki:About/zh-tw', 'zh', 'zh-tw', 'zh-cn' ],
|
|
|
|
|
[ 'en', 'MediaWiki:Common.js', 'zh', 'zh-tw', 'zh-cn' ],
|
|
|
|
|
[ 'en', 'MediaWiki:Common.css', 'zh', 'zh-tw', 'zh-cn' ],
|
|
|
|
|
[ 'en', 'User:JohnDoe/Common.js', 'zh', 'zh-tw', 'zh-cn' ],
|
|
|
|
|
[ 'en', 'User:JohnDoe/Monobook.css', 'zh', 'zh-tw', 'zh-cn' ],
|
|
|
|
|
|
|
|
|
|
[ 'zh-tw', 'Special:NewPages', 'es', 'zh-tw', 'zh-cn' ],
|
|
|
|
|
[ 'zh-tw', 'Special:NewPages', 'zh', 'zh-tw', 'zh-cn' ],
|
|
|
|
|
|
|
|
|
|
];
|
2012-06-02 18:07:46 +00:00
|
|
|
}
|
2012-08-30 20:04:42 +00:00
|
|
|
|
|
|
|
|
/**
|
2021-09-07 18:45:21 +00:00
|
|
|
* @dataProvider provideGetPageViewLanguage
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getPageViewLanguage
|
2012-08-30 20:04:42 +00:00
|
|
|
*/
|
2021-09-07 18:45:21 +00:00
|
|
|
public function testGetPageViewLanguage( $expected, $titleText, $contLang,
|
|
|
|
|
$lang, $variant, $msg = ''
|
|
|
|
|
) {
|
2022-07-06 15:05:30 +00:00
|
|
|
// Setup environment for this test
|
|
|
|
|
$this->overrideConfigValues( [
|
|
|
|
|
MainConfigNames::DefaultLanguageVariant => $variant,
|
|
|
|
|
MainConfigNames::AllowUserJs => true,
|
2021-09-07 18:45:21 +00:00
|
|
|
] );
|
|
|
|
|
$this->setUserLang( $lang );
|
2022-07-06 15:05:30 +00:00
|
|
|
$this->overrideConfigValue( MainConfigNames::LanguageCode, $contLang );
|
2012-08-30 20:04:42 +00:00
|
|
|
|
2021-09-07 18:45:21 +00:00
|
|
|
$title = Title::newFromText( $titleText );
|
|
|
|
|
$this->assertInstanceOf( Title::class, $title,
|
|
|
|
|
"Test must be passed a valid title text, you gave '$titleText'"
|
2019-06-14 09:01:22 +00:00
|
|
|
);
|
2021-09-07 18:45:21 +00:00
|
|
|
$this->assertEquals( $expected,
|
|
|
|
|
$title->getPageViewLanguage()->getCode(),
|
|
|
|
|
$msg
|
2019-06-14 09:01:22 +00:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-23 11:36:19 +00:00
|
|
|
public static function provideSubpage() {
|
2019-07-12 10:21:44 +00:00
|
|
|
// NOTE: avoid constructing Title objects in the provider, since it may access the database.
|
|
|
|
|
return [
|
|
|
|
|
[ 'Foo', 'x', new TitleValue( NS_MAIN, 'Foo/x' ) ],
|
|
|
|
|
[ 'Foo#bar', 'x', new TitleValue( NS_MAIN, 'Foo/x' ) ],
|
|
|
|
|
[ 'User:Foo', 'x', new TitleValue( NS_USER, 'Foo/x' ) ],
|
|
|
|
|
[ 'wiki:User:Foo', 'x', new TitleValue( NS_MAIN, 'User:Foo/x', '', 'wiki' ) ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideSubpage
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getSubpage
|
2019-07-12 10:21:44 +00:00
|
|
|
*/
|
|
|
|
|
public function testSubpage( $title, $sub, LinkTarget $expected ) {
|
|
|
|
|
$title = Title::newFromText( $title );
|
|
|
|
|
$expected = Title::newFromLinkTarget( $expected );
|
|
|
|
|
$actual = $title->getSubpage( $sub );
|
|
|
|
|
|
|
|
|
|
// NOTE: convert to string for comparison
|
|
|
|
|
$this->assertSame( $expected->getPrefixedText(), $actual->getPrefixedText(), 'text form' );
|
|
|
|
|
$this->assertTrue( $expected->equals( $actual ), 'Title equality' );
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-18 01:28:26 +00:00
|
|
|
public static function provideIsAlwaysKnown() {
|
2016-02-17 09:09:32 +00:00
|
|
|
return [
|
|
|
|
|
[ 'Some nonexistent page', false ],
|
|
|
|
|
[ 'UTPage', false ],
|
|
|
|
|
[ '#test', true ],
|
|
|
|
|
[ 'Special:BlankPage', true ],
|
|
|
|
|
[ 'Special:SomeNonexistentSpecialPage', false ],
|
|
|
|
|
[ 'MediaWiki:Parentheses', true ],
|
|
|
|
|
[ 'MediaWiki:Some nonexistent message', false ],
|
|
|
|
|
];
|
2014-06-19 18:36:56 +00:00
|
|
|
}
|
2014-08-21 19:54:51 +00:00
|
|
|
|
2017-06-12 19:11:42 +00:00
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::isAlwaysKnown
|
2021-09-07 18:45:21 +00:00
|
|
|
* @dataProvider provideIsAlwaysKnown
|
|
|
|
|
* @param string $page
|
|
|
|
|
* @param bool $isKnown
|
2017-06-12 19:11:42 +00:00
|
|
|
*/
|
2021-09-07 18:45:21 +00:00
|
|
|
public function testIsAlwaysKnown( $page, $isKnown ) {
|
|
|
|
|
$title = Title::newFromText( $page );
|
|
|
|
|
$this->assertEquals( $isKnown, $title->isAlwaysKnown() );
|
2017-06-12 19:11:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static function provideIsValid() {
|
|
|
|
|
return [
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, '' ), false ],
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, '<>' ), false ],
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, '|' ), false ],
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, '#' ), false ],
|
2019-08-29 17:09:05 +00:00
|
|
|
[ Title::makeTitle( NS_PROJECT, '#' ), false ],
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, '', 'test' ), true ],
|
|
|
|
|
[ Title::makeTitle( NS_PROJECT, '#test' ), false ],
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, '', 'test', 'wikipedia' ), true ],
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, 'Test', '', 'wikipedia' ), true ],
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, 'Test' ), true ],
|
|
|
|
|
[ Title::makeTitle( NS_SPECIAL, 'Test' ), true ],
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, ' Test' ), false ],
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, '_Test' ), false ],
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, 'Test ' ), false ],
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, 'Test_' ), false ],
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, "Test\nthis" ), false ],
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, "Test\tthis" ), false ],
|
|
|
|
|
[ Title::makeTitle( -33, 'Test' ), false ],
|
|
|
|
|
[ Title::makeTitle( 77663399, 'Test' ), false ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-24 21:29:49 +00:00
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::isValid
|
2021-09-07 18:45:21 +00:00
|
|
|
* @dataProvider provideIsValid
|
2021-03-24 21:29:49 +00:00
|
|
|
* @param Title $title
|
|
|
|
|
* @param bool $isValid
|
|
|
|
|
*/
|
2021-09-07 18:45:21 +00:00
|
|
|
public function testIsValid( Title $title, $isValid ) {
|
|
|
|
|
$this->assertEquals( $isValid, $title->isValid(), $title->getFullText() );
|
2021-03-24 21:29:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static function provideIsValidRedirectTarget() {
|
|
|
|
|
return [
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, '' ), false ],
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, '', 'test' ), false ],
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, 'Foo', 'test' ), true ],
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, '<>' ), false ],
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, '_' ), false ],
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, 'Test', '', 'acme' ), true ],
|
|
|
|
|
[ Title::makeTitle( NS_SPECIAL, 'UserLogout' ), false ],
|
|
|
|
|
[ Title::makeTitle( NS_SPECIAL, 'RecentChanges' ), true ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-07 18:45:21 +00:00
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::isValidRedirectTarget
|
2021-09-07 18:45:21 +00:00
|
|
|
* @dataProvider provideIsValidRedirectTarget
|
|
|
|
|
* @param Title $title
|
|
|
|
|
* @param bool $isValid
|
|
|
|
|
*/
|
|
|
|
|
public function testIsValidRedirectTarget( Title $title, $isValid ) {
|
|
|
|
|
// InterwikiLookup is configured in setUp()
|
|
|
|
|
$this->assertEquals( $isValid, $title->isValidRedirectTarget(), $title->getFullText() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static function provideCanExist() {
|
|
|
|
|
return [
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, '' ), false ],
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, '<>' ), false ],
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, '|' ), false ],
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, '#' ), false ],
|
|
|
|
|
[ Title::makeTitle( NS_PROJECT, '#test' ), false ],
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, '', 'test', 'acme' ), false ],
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, 'Test' ), true ],
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, ' Test' ), false ],
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, '_Test' ), false ],
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, 'Test ' ), false ],
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, 'Test_' ), false ],
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, "Test\nthis" ), false ],
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, "Test\tthis" ), false ],
|
|
|
|
|
[ Title::makeTitle( -33, 'Test' ), false ],
|
|
|
|
|
[ Title::makeTitle( 77663399, 'Test' ), false ],
|
|
|
|
|
|
|
|
|
|
// Valid but can't exist
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, '', 'test' ), false ],
|
|
|
|
|
[ Title::makeTitle( NS_SPECIAL, 'Test' ), false ],
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, 'Test', '', 'acme' ), false ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-29 17:09:05 +00:00
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::canExist
|
2019-08-29 17:09:05 +00:00
|
|
|
* @dataProvider provideCanExist
|
|
|
|
|
* @param Title $title
|
|
|
|
|
* @param bool $canExist
|
|
|
|
|
*/
|
|
|
|
|
public function testCanExist( Title $title, $canExist ) {
|
|
|
|
|
$this->assertEquals( $canExist, $title->canExist(), $title->getFullText() );
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-07 18:45:21 +00:00
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::isAlwaysKnown
|
2021-09-07 18:45:21 +00:00
|
|
|
*/
|
|
|
|
|
public function testIsAlwaysKnownOnInterwiki() {
|
|
|
|
|
$title = Title::makeTitle( NS_MAIN, 'Interwiki link', '', 'externalwiki' );
|
|
|
|
|
$this->assertTrue( $title->isAlwaysKnown() );
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-23 11:36:19 +00:00
|
|
|
public static function provideGetSkinFromConfigSubpage() {
|
2021-09-07 18:45:21 +00:00
|
|
|
return [
|
|
|
|
|
[ 'User:Foo', '' ],
|
|
|
|
|
[ 'User:Foo.css', '' ],
|
|
|
|
|
[ 'User:Foo/', '' ],
|
|
|
|
|
[ 'User:Foo/bar', '' ],
|
|
|
|
|
[ 'User:Foo./bar', '' ],
|
|
|
|
|
[ 'User:Foo/bar.', 'bar' ],
|
|
|
|
|
[ 'User:Foo/bar.css', 'bar' ],
|
|
|
|
|
[ '/bar.css', '' ],
|
|
|
|
|
[ '//bar.css', 'bar' ],
|
|
|
|
|
[ '.css', '' ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideGetSkinFromConfigSubpage
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getSkinFromConfigSubpage
|
2021-09-07 18:45:21 +00:00
|
|
|
*/
|
|
|
|
|
public function testGetSkinFromConfigSubpage( $title, $expected ) {
|
|
|
|
|
$title = Title::newFromText( $title );
|
|
|
|
|
$this->assertSame( $expected, $title->getSkinFromConfigSubpage() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getWikiId
|
2021-09-07 18:45:21 +00:00
|
|
|
*/
|
|
|
|
|
public function testGetWikiId() {
|
|
|
|
|
$title = Title::newFromText( 'Foo' );
|
|
|
|
|
$this->assertFalse( $title->getWikiId() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getFragment
|
|
|
|
|
* @covers MediaWiki\Title\Title::getFragment
|
|
|
|
|
* @covers MediaWiki\Title\Title::uncache
|
2021-09-07 18:45:21 +00:00
|
|
|
*/
|
|
|
|
|
public function testSetFragment() {
|
|
|
|
|
// NOTE: must use newFromText to test behavior of internal instance cache (T281337)
|
|
|
|
|
$title = Title::newFromText( 'Foo' );
|
|
|
|
|
|
|
|
|
|
$title->setFragment( '#Xyzzy' );
|
|
|
|
|
$this->assertSame( 'Xyzzy', $title->getFragment() );
|
|
|
|
|
|
|
|
|
|
// Ensure that the instance we get back from newFromText isn't the modified one.
|
|
|
|
|
$title = Title::newFromText( 'Foo' );
|
|
|
|
|
$this->assertNotSame( 'Xyzzy', $title->getFragment() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::__clone
|
2021-09-07 18:45:21 +00:00
|
|
|
*/
|
|
|
|
|
public function testClone() {
|
|
|
|
|
// NOTE: must use newFromText to test behavior of internal instance cache (T281337)
|
|
|
|
|
$title = Title::newFromText( 'Foo' );
|
|
|
|
|
|
|
|
|
|
$clone = clone $title;
|
|
|
|
|
$clone->setFragment( '#Xyzzy' );
|
|
|
|
|
|
|
|
|
|
// Ensure that the instance we get back from newFromText is the original one
|
|
|
|
|
$title2 = Title::newFromText( 'Foo' );
|
|
|
|
|
$this->assertSame( $title, $title2 );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static function provideBaseTitleCases() {
|
|
|
|
|
return [
|
|
|
|
|
# Namespace, Title text, expected base
|
|
|
|
|
[ NS_USER, 'John_Doe', 'John Doe' ],
|
|
|
|
|
[ NS_USER, 'John_Doe/subOne/subTwo', 'John Doe/subOne' ],
|
|
|
|
|
[ NS_USER, 'Foo / Bar / Baz', 'Foo / Bar ' ],
|
|
|
|
|
[ NS_USER, 'Foo/', 'Foo' ],
|
|
|
|
|
[ NS_USER, 'Foo/Bar/', 'Foo/Bar' ],
|
|
|
|
|
[ NS_USER, '/', '/' ],
|
|
|
|
|
[ NS_USER, '//', '/' ],
|
|
|
|
|
[ NS_USER, '/oops/', '/oops' ],
|
|
|
|
|
[ NS_USER, '/indeed', '/indeed' ],
|
|
|
|
|
[ NS_USER, '//indeed', '/' ],
|
|
|
|
|
[ NS_USER, '/Ramba/Zamba/Mamba/', '/Ramba/Zamba/Mamba' ],
|
|
|
|
|
[ NS_USER, '//x//y//z//', '//x//y//z/' ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideBaseTitleCases
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getBaseText
|
2021-09-07 18:45:21 +00:00
|
|
|
*/
|
|
|
|
|
public function testGetBaseText( $namespace, $title, $expected ) {
|
|
|
|
|
$title = Title::makeTitle( $namespace, $title );
|
|
|
|
|
$this->assertSame( $expected, $title->getBaseText() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideBaseTitleCases
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getBaseTitle
|
2021-09-07 18:45:21 +00:00
|
|
|
*/
|
|
|
|
|
public function testGetBaseTitle( $namespace, $title, $expected ) {
|
|
|
|
|
$title = Title::makeTitle( $namespace, $title );
|
|
|
|
|
$base = $title->getBaseTitle();
|
|
|
|
|
$this->assertTrue( $base->isValid() );
|
|
|
|
|
$this->assertTrue(
|
|
|
|
|
$base->equals( Title::makeTitleSafe( $title->getNamespace(), $expected ) )
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static function provideRootTitleCases() {
|
|
|
|
|
return [
|
|
|
|
|
# Namespace, Title, expected base
|
|
|
|
|
[ NS_USER, 'John_Doe', 'John Doe' ],
|
|
|
|
|
[ NS_USER, 'John_Doe/subOne/subTwo', 'John Doe' ],
|
|
|
|
|
[ NS_USER, 'Foo / Bar / Baz', 'Foo ' ],
|
|
|
|
|
[ NS_USER, 'Foo/', 'Foo' ],
|
|
|
|
|
[ NS_USER, 'Foo/Bar/', 'Foo' ],
|
|
|
|
|
[ NS_USER, '/', '/' ],
|
|
|
|
|
[ NS_USER, '//', '/' ],
|
|
|
|
|
[ NS_USER, '/oops/', '/oops' ],
|
|
|
|
|
[ NS_USER, '/Ramba/Zamba/Mamba/', '/Ramba' ],
|
|
|
|
|
[ NS_USER, '//x//y//z//', '//x' ],
|
|
|
|
|
[ NS_TALK, '////', '///' ],
|
|
|
|
|
[ NS_TEMPLATE, '////', '///' ],
|
|
|
|
|
[ NS_TEMPLATE, 'Foo////', 'Foo' ],
|
|
|
|
|
[ NS_TEMPLATE, 'Foo////Bar', 'Foo' ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideRootTitleCases
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getRootText
|
2021-09-07 18:45:21 +00:00
|
|
|
*/
|
|
|
|
|
public function testGetRootText( $namespace, $title, $expected ) {
|
|
|
|
|
$title = Title::makeTitle( $namespace, $title );
|
|
|
|
|
$this->assertEquals( $expected, $title->getRootText() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideRootTitleCases
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getRootTitle
|
2021-09-07 18:45:21 +00:00
|
|
|
*/
|
|
|
|
|
public function testGetRootTitle( $namespace, $title, $expected ) {
|
|
|
|
|
$title = Title::makeTitle( $namespace, $title );
|
|
|
|
|
$root = $title->getRootTitle();
|
|
|
|
|
$this->assertTrue( $root->isValid() );
|
|
|
|
|
$this->assertTrue(
|
|
|
|
|
$root->equals( Title::makeTitleSafe( $title->getNamespace(), $expected ) )
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static function provideSubpageTitleCases() {
|
|
|
|
|
return [
|
|
|
|
|
# Namespace, Title, expected base
|
|
|
|
|
[ NS_USER, 'John_Doe', 'John Doe' ],
|
|
|
|
|
[ NS_USER, 'John_Doe/subOne/subTwo', 'subTwo' ],
|
|
|
|
|
[ NS_USER, 'John_Doe/subOne', 'subOne' ],
|
|
|
|
|
[ NS_USER, '/', '/' ],
|
|
|
|
|
[ NS_USER, '//', '' ],
|
|
|
|
|
[ NS_USER, '/oops/', '' ],
|
|
|
|
|
[ NS_USER, '/indeed', '/indeed' ],
|
|
|
|
|
[ NS_USER, '//indeed', 'indeed' ],
|
|
|
|
|
[ NS_USER, '/Ramba/Zamba/Mamba/', '' ],
|
|
|
|
|
[ NS_USER, '//x//y//z//', '' ],
|
|
|
|
|
[ NS_TEMPLATE, 'Foo', 'Foo' ],
|
|
|
|
|
[ NS_CATEGORY, 'Foo', 'Foo' ],
|
|
|
|
|
[ NS_MAIN, 'Bar', 'Bar' ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideSubpageTitleCases
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getSubpageText
|
2021-09-07 18:45:21 +00:00
|
|
|
*/
|
|
|
|
|
public function testGetSubpageText( $namespace, $title, $expected ) {
|
|
|
|
|
$title = Title::makeTitle( $namespace, $title );
|
|
|
|
|
$this->assertEquals( $expected, $title->getSubpageText() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static function provideGetTitleValue() {
|
|
|
|
|
return [
|
|
|
|
|
[ 'Foo' ],
|
|
|
|
|
[ 'Foo#bar' ],
|
|
|
|
|
[ 'User:Hansi_Maier' ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getTitleValue
|
2021-09-07 18:45:21 +00:00
|
|
|
* @dataProvider provideGetTitleValue
|
|
|
|
|
*/
|
|
|
|
|
public function testGetTitleValue( $text ) {
|
|
|
|
|
$title = Title::newFromText( $text );
|
|
|
|
|
$value = $title->getTitleValue();
|
|
|
|
|
|
|
|
|
|
$dbkey = str_replace( ' ', '_', $value->getText() );
|
|
|
|
|
$this->assertEquals( $title->getDBkey(), $dbkey );
|
|
|
|
|
$this->assertEquals( $title->getNamespace(), $value->getNamespace() );
|
|
|
|
|
$this->assertEquals( $title->getFragment(), $value->getFragment() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static function provideGetFragment() {
|
2019-08-29 17:09:05 +00:00
|
|
|
return [
|
2021-09-07 18:45:21 +00:00
|
|
|
[ 'Foo', '' ],
|
|
|
|
|
[ 'Foo#bar', 'bar' ],
|
|
|
|
|
[ 'Foo#bär', 'bär' ],
|
2019-08-29 17:09:05 +00:00
|
|
|
|
2021-09-07 18:45:21 +00:00
|
|
|
// Inner whitespace is normalized
|
|
|
|
|
[ 'Foo#bar_bar', 'bar bar' ],
|
|
|
|
|
[ 'Foo#bar bar', 'bar bar' ],
|
|
|
|
|
[ 'Foo#bar bar', 'bar bar' ],
|
|
|
|
|
|
|
|
|
|
// Leading whitespace is kept, trailing whitespace is trimmed.
|
|
|
|
|
// XXX: Is this really want we want?
|
|
|
|
|
[ 'Foo#_bar_bar_', ' bar bar' ],
|
|
|
|
|
[ 'Foo# bar bar ', ' bar bar' ],
|
2017-06-12 19:11:42 +00:00
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-21 19:54:51 +00:00
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getFragment
|
2021-09-07 18:45:21 +00:00
|
|
|
* @dataProvider provideGetFragment
|
|
|
|
|
*
|
|
|
|
|
* @param string $full
|
|
|
|
|
* @param string $fragment
|
2014-08-21 19:54:51 +00:00
|
|
|
*/
|
2021-09-07 18:45:21 +00:00
|
|
|
public function testGetFragment( $full, $fragment ) {
|
|
|
|
|
$title = Title::newFromText( $full );
|
|
|
|
|
$this->assertEquals( $fragment, $title->getFragment() );
|
2014-08-21 19:54:51 +00:00
|
|
|
}
|
2015-04-30 18:55:23 +00:00
|
|
|
|
|
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::exists
|
2015-04-30 18:55:23 +00:00
|
|
|
*/
|
|
|
|
|
public function testExists() {
|
|
|
|
|
$title = Title::makeTitle( NS_PROJECT, 'New page' );
|
2022-01-12 20:13:39 +00:00
|
|
|
$linkCache = $this->getServiceContainer()->getLinkCache();
|
2015-04-30 18:55:23 +00:00
|
|
|
|
|
|
|
|
$article = new Article( $title );
|
|
|
|
|
$page = $article->getPage();
|
2021-06-24 08:42:19 +00:00
|
|
|
$page->doUserEditContent(
|
|
|
|
|
new WikitextContent( 'Some [[link]]' ),
|
|
|
|
|
$this->getTestSysop()->getUser(),
|
|
|
|
|
'summary'
|
|
|
|
|
);
|
2015-04-30 18:55:23 +00:00
|
|
|
|
|
|
|
|
// Tell Title it doesn't know whether it exists
|
|
|
|
|
$title->mArticleID = -1;
|
|
|
|
|
|
2019-08-08 13:01:15 +00:00
|
|
|
// Tell the link cache it doesn't exist when it really does
|
2015-04-30 18:55:23 +00:00
|
|
|
$linkCache->clearLink( $title );
|
|
|
|
|
$linkCache->addBadLinkObj( $title );
|
|
|
|
|
|
2019-09-17 14:19:26 +00:00
|
|
|
$this->assertFalse(
|
2015-09-30 08:01:28 +00:00
|
|
|
$title->exists(),
|
2019-07-04 21:24:34 +00:00
|
|
|
'exists() should rely on link cache unless READ_LATEST is used'
|
2015-09-30 08:01:28 +00:00
|
|
|
);
|
2020-01-09 23:23:19 +00:00
|
|
|
$this->assertTrue(
|
2019-07-04 21:24:34 +00:00
|
|
|
$title->exists( Title::READ_LATEST ),
|
|
|
|
|
'exists() should re-query database when READ_LATEST is used'
|
2015-09-30 08:01:28 +00:00
|
|
|
);
|
2015-04-30 18:55:23 +00:00
|
|
|
}
|
2016-04-20 08:09:23 +00:00
|
|
|
|
2020-12-03 08:52:55 +00:00
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getArticleID
|
|
|
|
|
* @covers MediaWiki\Title\Title::getId
|
2020-12-03 08:52:55 +00:00
|
|
|
*/
|
|
|
|
|
public function testGetArticleID() {
|
|
|
|
|
$title = Title::makeTitle( NS_PROJECT, __METHOD__ );
|
|
|
|
|
$this->assertSame( 0, $title->getArticleID() );
|
|
|
|
|
$this->assertSame( $title->getArticleID(), $title->getId() );
|
|
|
|
|
|
|
|
|
|
$article = new Article( $title );
|
|
|
|
|
$page = $article->getPage();
|
2021-06-24 08:42:19 +00:00
|
|
|
$page->doUserEditContent(
|
|
|
|
|
new WikitextContent( 'Some [[link]]' ),
|
|
|
|
|
$this->getTestSysop()->getUser(),
|
|
|
|
|
'summary'
|
|
|
|
|
);
|
2020-12-03 08:52:55 +00:00
|
|
|
|
|
|
|
|
$this->assertGreaterThan( 0, $title->getArticleID() );
|
|
|
|
|
$this->assertSame( $title->getArticleID(), $title->getId() );
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-23 11:36:19 +00:00
|
|
|
public static function provideNonProperTitles() {
|
2021-06-01 20:14:36 +00:00
|
|
|
return [
|
|
|
|
|
'section link' => [ Title::makeTitle( NS_MAIN, '', 'Section' ) ],
|
|
|
|
|
'empty' => [ Title::makeTitle( NS_MAIN, '' ) ],
|
|
|
|
|
'bad chars' => [ Title::makeTitle( NS_MAIN, '_|_' ) ],
|
|
|
|
|
'empty in namspace' => [ Title::makeTitle( NS_USER, '' ) ],
|
|
|
|
|
'special' => [ Title::makeTitle( NS_SPECIAL, 'RecentChanges' ) ],
|
|
|
|
|
'interwiki' => [ Title::makeTitle( NS_MAIN, 'Test', '', 'acme' ) ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideNonProperTitles
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getArticleID
|
2021-06-01 20:14:36 +00:00
|
|
|
*/
|
|
|
|
|
public function testGetArticleIDFromNonProperTitle( $title ) {
|
|
|
|
|
// make sure nothing explodes
|
|
|
|
|
$this->assertSame( 0, $title->getArticleID() );
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-23 11:36:19 +00:00
|
|
|
public static function provideCanHaveTalkPage() {
|
2017-06-09 18:29:18 +00:00
|
|
|
return [
|
|
|
|
|
'User page has talk page' => [
|
|
|
|
|
Title::makeTitle( NS_USER, 'Jane' ), true
|
|
|
|
|
],
|
|
|
|
|
'Talke page has talk page' => [
|
|
|
|
|
Title::makeTitle( NS_TALK, 'Foo' ), true
|
|
|
|
|
],
|
|
|
|
|
'Special page cannot have talk page' => [
|
|
|
|
|
Title::makeTitle( NS_SPECIAL, 'Thing' ), false
|
|
|
|
|
],
|
|
|
|
|
'Virtual namespace cannot have talk page' => [
|
|
|
|
|
Title::makeTitle( NS_MEDIA, 'Kitten.jpg' ), false
|
|
|
|
|
],
|
2019-06-03 22:56:22 +00:00
|
|
|
'Relative link has no talk page' => [
|
|
|
|
|
Title::makeTitle( NS_MAIN, '', 'Kittens' ), false
|
|
|
|
|
],
|
|
|
|
|
'Interwiki link has no talk page' => [
|
|
|
|
|
Title::makeTitle( NS_MAIN, 'Kittens', '', 'acme' ), false
|
|
|
|
|
],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static function provideGetTalkPage_good() {
|
|
|
|
|
return [
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, 'Test' ), Title::makeTitle( NS_TALK, 'Test' ) ],
|
|
|
|
|
[ Title::makeTitle( NS_TALK, 'Test' ), Title::makeTitle( NS_TALK, 'Test' ) ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static function provideGetTalkPage_bad() {
|
|
|
|
|
return [
|
|
|
|
|
[ Title::makeTitle( NS_SPECIAL, 'Test' ) ],
|
|
|
|
|
[ Title::makeTitle( NS_MEDIA, 'Test' ) ],
|
2019-08-29 13:25:16 +00:00
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static function provideGetTalkPage_broken() {
|
|
|
|
|
// These cases *should* be bad, but are not treated as bad, for backwards compatibility.
|
|
|
|
|
// See discussion on T227817.
|
|
|
|
|
return [
|
|
|
|
|
[
|
|
|
|
|
Title::makeTitle( NS_MAIN, '', 'Kittens' ),
|
|
|
|
|
Title::makeTitle( NS_TALK, '' ), // Section is lost!
|
|
|
|
|
false,
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
Title::makeTitle( NS_MAIN, 'Kittens', '', 'acme' ),
|
|
|
|
|
Title::makeTitle( NS_TALK, 'Kittens', '' ), // Interwiki prefix is lost!
|
|
|
|
|
true,
|
|
|
|
|
],
|
2019-06-03 22:56:22 +00:00
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static function provideGetSubjectPage_good() {
|
|
|
|
|
return [
|
|
|
|
|
[ Title::makeTitle( NS_TALK, 'Test' ), Title::makeTitle( NS_MAIN, 'Test' ) ],
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, 'Test' ), Title::makeTitle( NS_MAIN, 'Test' ) ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static function provideGetOtherPage_good() {
|
|
|
|
|
return [
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, 'Test' ), Title::makeTitle( NS_TALK, 'Test' ) ],
|
|
|
|
|
[ Title::makeTitle( NS_TALK, 'Test' ), Title::makeTitle( NS_MAIN, 'Test' ) ],
|
2017-06-09 18:29:18 +00:00
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideCanHaveTalkPage
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::canHaveTalkPage
|
2017-06-09 18:29:18 +00:00
|
|
|
*
|
|
|
|
|
* @param Title $title
|
|
|
|
|
* @param bool $expected
|
|
|
|
|
*/
|
|
|
|
|
public function testCanHaveTalkPage( Title $title, $expected ) {
|
|
|
|
|
$actual = $title->canHaveTalkPage();
|
|
|
|
|
$this->assertSame( $expected, $actual, $title->getPrefixedDBkey() );
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-01 17:09:13 +00:00
|
|
|
/**
|
|
|
|
|
* @dataProvider provideGetTalkPage_good
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getTalkPageIfDefined
|
2017-08-01 17:09:13 +00:00
|
|
|
*/
|
2019-06-03 22:56:22 +00:00
|
|
|
public function testGetTalkPage_good( Title $title, Title $expected ) {
|
|
|
|
|
$actual = $title->getTalkPage();
|
|
|
|
|
$this->assertTrue( $expected->equals( $actual ), $title->getPrefixedDBkey() );
|
2017-08-01 17:09:13 +00:00
|
|
|
}
|
|
|
|
|
|
2019-06-03 22:56:22 +00:00
|
|
|
/**
|
|
|
|
|
* @dataProvider provideGetTalkPage_bad
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getTalkPageIfDefined
|
2019-06-03 22:56:22 +00:00
|
|
|
*/
|
|
|
|
|
public function testGetTalkPage_bad( Title $title ) {
|
2019-10-05 22:14:35 +00:00
|
|
|
$this->expectException( MWException::class );
|
2019-06-03 22:56:22 +00:00
|
|
|
$title->getTalkPage();
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-29 13:25:16 +00:00
|
|
|
/**
|
|
|
|
|
* @dataProvider provideGetTalkPage_broken
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getTalkPageIfDefined
|
2019-08-29 13:25:16 +00:00
|
|
|
*/
|
|
|
|
|
public function testGetTalkPage_broken( Title $title, Title $expected, $valid ) {
|
|
|
|
|
// NOTE: Eventually we want to throw in this case. But while there is still code that
|
|
|
|
|
// calls this method without checking, we want to avoid fatal errors.
|
|
|
|
|
// See discussion on T227817.
|
2022-02-24 19:57:59 +00:00
|
|
|
$result = @$title->getTalkPage();
|
2019-08-29 13:25:16 +00:00
|
|
|
$this->assertTrue( $expected->equals( $result ) );
|
|
|
|
|
$this->assertSame( $valid, $result->isValid() );
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-03 22:56:22 +00:00
|
|
|
/**
|
|
|
|
|
* @dataProvider provideGetTalkPage_good
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getTalkPageIfDefined
|
2019-06-03 22:56:22 +00:00
|
|
|
*/
|
|
|
|
|
public function testGetTalkPageIfDefined_good( Title $title, Title $expected ) {
|
|
|
|
|
$actual = $title->getTalkPageIfDefined();
|
|
|
|
|
$this->assertNotNull( $actual, $title->getPrefixedDBkey() );
|
|
|
|
|
$this->assertTrue( $expected->equals( $actual ), $title->getPrefixedDBkey() );
|
2017-08-01 17:09:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideGetTalkPage_bad
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getTalkPageIfDefined
|
2017-08-01 17:09:13 +00:00
|
|
|
*/
|
|
|
|
|
public function testGetTalkPageIfDefined_bad( Title $title ) {
|
|
|
|
|
$talk = $title->getTalkPageIfDefined();
|
|
|
|
|
$this->assertNull(
|
|
|
|
|
$talk,
|
2019-06-03 22:56:22 +00:00
|
|
|
$title->getPrefixedDBkey()
|
2017-08-01 17:09:13 +00:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-03 22:56:22 +00:00
|
|
|
/**
|
|
|
|
|
* @dataProvider provideGetSubjectPage_good
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getSubjectPage
|
2019-06-03 22:56:22 +00:00
|
|
|
*/
|
|
|
|
|
public function testGetSubjectPage_good( Title $title, Title $expected ) {
|
|
|
|
|
$actual = $title->getSubjectPage();
|
|
|
|
|
$this->assertTrue( $expected->equals( $actual ), $title->getPrefixedDBkey() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideGetOtherPage_good
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getOtherPage
|
2019-06-03 22:56:22 +00:00
|
|
|
*/
|
|
|
|
|
public function testGetOtherPage_good( Title $title, Title $expected ) {
|
|
|
|
|
$actual = $title->getOtherPage();
|
|
|
|
|
$this->assertTrue( $expected->equals( $actual ), $title->getPrefixedDBkey() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideGetTalkPage_bad
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getOtherPage
|
2019-06-03 22:56:22 +00:00
|
|
|
*/
|
|
|
|
|
public function testGetOtherPage_bad( Title $title ) {
|
2019-10-05 22:14:35 +00:00
|
|
|
$this->expectException( MWException::class );
|
2019-06-03 22:56:22 +00:00
|
|
|
$title->getOtherPage();
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-06 09:47:46 +00:00
|
|
|
public static function provideIsMovable() {
|
|
|
|
|
return [
|
|
|
|
|
'Simple title' => [ 'Foo', true ],
|
|
|
|
|
// @todo Should these next two really be true?
|
|
|
|
|
'Empty name' => [ Title::makeTitle( NS_MAIN, '' ), true ],
|
|
|
|
|
'Invalid name' => [ Title::makeTitle( NS_MAIN, '<' ), true ],
|
|
|
|
|
'Interwiki' => [ Title::makeTitle( NS_MAIN, 'Test', '', 'otherwiki' ), false ],
|
|
|
|
|
'Special page' => [ 'Special:FooBar', false ],
|
|
|
|
|
'Aborted by hook' => [ 'Hooked in place', false,
|
2021-02-07 13:10:36 +00:00
|
|
|
static function ( Title $title, &$result ) {
|
2019-05-06 09:47:46 +00:00
|
|
|
$result = false;
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-20 08:09:23 +00:00
|
|
|
/**
|
2021-09-07 18:45:21 +00:00
|
|
|
* @dataProvider provideIsMovable
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::isMovable
|
2021-09-07 18:45:21 +00:00
|
|
|
*
|
|
|
|
|
* @param string|Title $title
|
|
|
|
|
* @param bool $expected
|
|
|
|
|
* @param callable|null $hookCallback For TitleIsMovable
|
2016-04-20 08:09:23 +00:00
|
|
|
*/
|
2021-09-07 18:45:21 +00:00
|
|
|
public function testIsMovable( $title, $expected, $hookCallback = null ) {
|
|
|
|
|
if ( $hookCallback ) {
|
|
|
|
|
$this->setTemporaryHook( 'TitleIsMovable', $hookCallback );
|
|
|
|
|
}
|
|
|
|
|
if ( is_string( $title ) ) {
|
|
|
|
|
$title = Title::newFromText( $title );
|
|
|
|
|
}
|
2016-04-20 08:09:23 +00:00
|
|
|
|
2021-09-07 18:45:21 +00:00
|
|
|
$this->assertSame( $expected, $title->isMovable() );
|
2016-04-20 08:09:23 +00:00
|
|
|
}
|
2016-05-12 18:14:47 +00:00
|
|
|
|
2023-03-23 11:36:19 +00:00
|
|
|
public static function provideGetPrefixedText() {
|
2016-05-12 18:14:47 +00:00
|
|
|
return [
|
|
|
|
|
// ns = 0
|
|
|
|
|
[
|
2017-06-09 16:39:33 +00:00
|
|
|
Title::makeTitle( NS_MAIN, 'Foo bar' ),
|
|
|
|
|
'Foo bar'
|
2016-05-12 18:14:47 +00:00
|
|
|
],
|
|
|
|
|
// ns = 2
|
|
|
|
|
[
|
2017-06-09 16:39:33 +00:00
|
|
|
Title::makeTitle( NS_USER, 'Foo bar' ),
|
|
|
|
|
'User:Foo bar'
|
|
|
|
|
],
|
|
|
|
|
// ns = 3
|
|
|
|
|
[
|
|
|
|
|
Title::makeTitle( NS_USER_TALK, 'Foo bar' ),
|
|
|
|
|
'User talk:Foo bar'
|
2016-05-12 18:14:47 +00:00
|
|
|
],
|
|
|
|
|
// fragment not included
|
|
|
|
|
[
|
2017-06-09 16:39:33 +00:00
|
|
|
Title::makeTitle( NS_MAIN, 'Foo bar', 'fragment' ),
|
|
|
|
|
'Foo bar'
|
2016-05-12 18:14:47 +00:00
|
|
|
],
|
|
|
|
|
// ns = -2
|
|
|
|
|
[
|
2017-06-09 16:39:33 +00:00
|
|
|
Title::makeTitle( NS_MEDIA, 'Foo bar' ),
|
|
|
|
|
'Media:Foo bar'
|
2016-05-12 18:14:47 +00:00
|
|
|
],
|
|
|
|
|
// non-existent namespace
|
|
|
|
|
[
|
2017-06-09 16:39:33 +00:00
|
|
|
Title::makeTitle( 100777, 'Foo bar' ),
|
|
|
|
|
'Special:Badtitle/NS100777:Foo bar'
|
2016-05-12 18:14:47 +00:00
|
|
|
],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getPrefixedText
|
2016-05-12 18:14:47 +00:00
|
|
|
* @dataProvider provideGetPrefixedText
|
|
|
|
|
*/
|
|
|
|
|
public function testGetPrefixedText( Title $title, $expected ) {
|
|
|
|
|
$this->assertEquals( $expected, $title->getPrefixedText() );
|
|
|
|
|
}
|
2017-06-09 16:39:33 +00:00
|
|
|
|
2023-03-23 11:36:19 +00:00
|
|
|
public static function provideGetPrefixedDBKey() {
|
2017-06-09 16:39:33 +00:00
|
|
|
return [
|
|
|
|
|
// ns = 0
|
|
|
|
|
[
|
|
|
|
|
Title::makeTitle( NS_MAIN, 'Foo_bar' ),
|
|
|
|
|
'Foo_bar'
|
|
|
|
|
],
|
|
|
|
|
// ns = 2
|
|
|
|
|
[
|
|
|
|
|
Title::makeTitle( NS_USER, 'Foo_bar' ),
|
|
|
|
|
'User:Foo_bar'
|
|
|
|
|
],
|
|
|
|
|
// ns = 3
|
|
|
|
|
[
|
|
|
|
|
Title::makeTitle( NS_USER_TALK, 'Foo_bar' ),
|
|
|
|
|
'User_talk:Foo_bar'
|
|
|
|
|
],
|
|
|
|
|
// fragment not included
|
|
|
|
|
[
|
|
|
|
|
Title::makeTitle( NS_MAIN, 'Foo_bar', 'fragment' ),
|
|
|
|
|
'Foo_bar'
|
|
|
|
|
],
|
|
|
|
|
// ns = -2
|
|
|
|
|
[
|
|
|
|
|
Title::makeTitle( NS_MEDIA, 'Foo_bar' ),
|
|
|
|
|
'Media:Foo_bar'
|
|
|
|
|
],
|
|
|
|
|
// non-existent namespace
|
|
|
|
|
[
|
|
|
|
|
Title::makeTitle( 100777, 'Foo_bar' ),
|
|
|
|
|
'Special:Badtitle/NS100777:Foo_bar'
|
|
|
|
|
],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getPrefixedDBKey
|
2017-06-09 16:39:33 +00:00
|
|
|
* @dataProvider provideGetPrefixedDBKey
|
|
|
|
|
*/
|
|
|
|
|
public function testGetPrefixedDBKey( Title $title, $expected ) {
|
|
|
|
|
$this->assertEquals( $expected, $title->getPrefixedDBkey() );
|
|
|
|
|
}
|
2017-11-28 23:17:46 +00:00
|
|
|
|
2023-03-23 11:36:19 +00:00
|
|
|
public static function provideGetFragmentForURL() {
|
2021-09-07 18:45:21 +00:00
|
|
|
return [
|
|
|
|
|
[ 'Foo', '' ],
|
|
|
|
|
[ 'Foo#ümlåût', '#ümlåût' ],
|
|
|
|
|
[ 'de:Foo#Bå®', '#Bå®' ],
|
|
|
|
|
[ 'zz:Foo#тест', '#.D1.82.D0.B5.D1.81.D1.82' ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-28 23:17:46 +00:00
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getFragmentForURL
|
2017-11-28 23:17:46 +00:00
|
|
|
* @dataProvider provideGetFragmentForURL
|
|
|
|
|
*
|
|
|
|
|
* @param string $titleStr
|
|
|
|
|
* @param string $expected
|
|
|
|
|
*/
|
|
|
|
|
public function testGetFragmentForURL( $titleStr, $expected ) {
|
2022-07-06 15:05:30 +00:00
|
|
|
$this->overrideConfigValues( [
|
|
|
|
|
MainConfigNames::FragmentMode => [ 'html5' ],
|
|
|
|
|
MainConfigNames::ExternalInterwikiFragmentMode => 'legacy',
|
2017-11-28 23:17:46 +00:00
|
|
|
] );
|
2021-05-05 00:03:26 +00:00
|
|
|
// InterwikiLookup is configured in setUp()
|
2017-11-28 23:17:46 +00:00
|
|
|
|
|
|
|
|
$title = Title::newFromText( $titleStr );
|
|
|
|
|
self::assertEquals( $expected, $title->getFragmentForURL() );
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-23 11:36:19 +00:00
|
|
|
public static function provideIsRawHtmlMessage() {
|
2017-11-28 23:17:46 +00:00
|
|
|
return [
|
2021-09-07 18:45:21 +00:00
|
|
|
[ 'MediaWiki:Foobar', true ],
|
|
|
|
|
[ 'MediaWiki:Foo bar', true ],
|
|
|
|
|
[ 'MediaWiki:Foo-bar', true ],
|
|
|
|
|
[ 'MediaWiki:foo bar', true ],
|
|
|
|
|
[ 'MediaWiki:foo-bar', true ],
|
|
|
|
|
[ 'MediaWiki:foobar', true ],
|
|
|
|
|
[ 'MediaWiki:some-other-message', false ],
|
|
|
|
|
[ 'Main Page', false ],
|
2017-11-28 23:17:46 +00:00
|
|
|
];
|
|
|
|
|
}
|
2018-08-28 19:47:49 +00:00
|
|
|
|
|
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::isRawHtmlMessage
|
2018-08-28 19:47:49 +00:00
|
|
|
* @dataProvider provideIsRawHtmlMessage
|
|
|
|
|
*/
|
|
|
|
|
public function testIsRawHtmlMessage( $textForm, $expected ) {
|
2022-07-06 15:05:30 +00:00
|
|
|
$this->overrideConfigValue(
|
|
|
|
|
MainConfigNames::RawHtmlMessages,
|
|
|
|
|
[
|
|
|
|
|
'foobar',
|
|
|
|
|
'foo_bar',
|
|
|
|
|
'foo-bar',
|
|
|
|
|
]
|
|
|
|
|
);
|
2018-08-28 19:47:49 +00:00
|
|
|
|
|
|
|
|
$title = Title::newFromText( $textForm );
|
|
|
|
|
$this->assertSame( $expected, $title->isRawHtmlMessage() );
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-13 03:27:31 +00:00
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::newMainPage
|
2019-04-13 03:27:31 +00:00
|
|
|
*/
|
|
|
|
|
public function testNewMainPage() {
|
2019-04-08 15:21:49 +00:00
|
|
|
$mock = $this->createMock( MessageCache::class );
|
|
|
|
|
$mock->method( 'get' )->willReturn( 'Foresheet' );
|
|
|
|
|
$mock->method( 'transform' )->willReturn( 'Foresheet' );
|
|
|
|
|
|
|
|
|
|
$this->setService( 'MessageCache', $mock );
|
2019-04-13 03:27:31 +00:00
|
|
|
|
|
|
|
|
$this->assertSame(
|
|
|
|
|
'Foresheet',
|
|
|
|
|
Title::newMainPage()->getText()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-12 20:05:22 +00:00
|
|
|
/**
|
|
|
|
|
* Regression test for T297571
|
|
|
|
|
*
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::newMainPage
|
2021-12-12 20:05:22 +00:00
|
|
|
*/
|
|
|
|
|
public function testNewMainPageNoRecursion() {
|
|
|
|
|
$mock = $this->createMock( MessageCache::class );
|
|
|
|
|
$mock->method( 'get' )->willReturn( 'localtestiw:' );
|
|
|
|
|
$mock->method( 'transform' )->willReturn( 'localtestiw:' );
|
|
|
|
|
$this->setService( 'MessageCache', $mock );
|
|
|
|
|
|
|
|
|
|
$this->assertSame(
|
|
|
|
|
'Main Page',
|
|
|
|
|
Title::newMainPage()->getPrefixedText()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-13 03:27:31 +00:00
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::newMainPage
|
2019-04-13 03:27:31 +00:00
|
|
|
*/
|
|
|
|
|
public function testNewMainPageWithLocal() {
|
|
|
|
|
$local = $this->createMock( MessageLocalizer::class );
|
|
|
|
|
$local->method( 'msg' )->willReturn( new RawMessage( 'Prime Article' ) );
|
|
|
|
|
|
|
|
|
|
$this->assertSame(
|
|
|
|
|
'Prime Article',
|
|
|
|
|
Title::newMainPage( $local )->getText()
|
|
|
|
|
);
|
|
|
|
|
}
|
2019-11-07 19:06:55 +00:00
|
|
|
|
|
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getTitleProtection
|
2019-11-07 19:06:55 +00:00
|
|
|
*/
|
|
|
|
|
public function testGetTitleProtection() {
|
|
|
|
|
$title = $this->getNonexistingTestPage( 'UTest1' )->getTitle();
|
2020-12-23 10:03:34 +00:00
|
|
|
$this->assertFalse( $title->getTitleProtection() );
|
2019-11-07 19:06:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::deleteTitleProtection
|
2019-11-07 19:06:55 +00:00
|
|
|
*/
|
|
|
|
|
public function testDeleteTitleProtection() {
|
|
|
|
|
$title = $this->getExistingTestPage( 'UTest1' )->getTitle();
|
2020-12-23 10:03:34 +00:00
|
|
|
$this->assertFalse( $title->getTitleProtection() );
|
2019-11-07 19:06:55 +00:00
|
|
|
}
|
|
|
|
|
|
2020-04-17 17:39:53 +00:00
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getCdnUrls
|
2020-04-17 17:39:53 +00:00
|
|
|
*/
|
|
|
|
|
public function testGetCdnUrls() {
|
|
|
|
|
$this->assertEquals(
|
|
|
|
|
[
|
|
|
|
|
'https://example.org/wiki/Example',
|
|
|
|
|
'https://example.org/w/index.php?title=Example&action=history',
|
|
|
|
|
],
|
|
|
|
|
Title::makeTitle( NS_MAIN, 'Example' )->getCdnUrls(),
|
|
|
|
|
'article'
|
|
|
|
|
);
|
|
|
|
|
}
|
2021-03-22 22:42:20 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers \MediaWiki\Page\PageStore::getSubpages
|
|
|
|
|
*/
|
|
|
|
|
public function testGetSubpages() {
|
|
|
|
|
$existingPage = $this->getExistingTestPage();
|
|
|
|
|
$title = $existingPage->getTitle();
|
|
|
|
|
|
2022-07-06 15:05:30 +00:00
|
|
|
$this->overrideConfigValue(
|
|
|
|
|
MainConfigNames::NamespacesWithSubpages,
|
|
|
|
|
[ $title->getNamespace() => true ]
|
|
|
|
|
);
|
2021-03-22 22:42:20 +00:00
|
|
|
|
|
|
|
|
$this->getExistingTestPage( $title->getSubpage( 'A' ) );
|
|
|
|
|
$this->getExistingTestPage( $title->getSubpage( 'B' ) );
|
|
|
|
|
|
|
|
|
|
$notQuiteSubpageTitle = $title->getPrefixedDBkey() . 'X'; // no slash!
|
|
|
|
|
$this->getExistingTestPage( $notQuiteSubpageTitle );
|
|
|
|
|
|
|
|
|
|
$subpages = iterator_to_array( $title->getSubpages() );
|
|
|
|
|
|
|
|
|
|
$this->assertCount( 2, $subpages );
|
|
|
|
|
$this->assertCount( 1, $title->getSubpages( 1 ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers \MediaWiki\Page\PageStore::getSubpages
|
|
|
|
|
*/
|
|
|
|
|
public function testGetSubpages_disabled() {
|
2022-07-06 15:05:30 +00:00
|
|
|
$this->overrideConfigValue( MainConfigNames::NamespacesWithSubpages, [] );
|
2021-03-22 22:42:20 +00:00
|
|
|
|
|
|
|
|
$existingPage = $this->getExistingTestPage();
|
|
|
|
|
$title = $existingPage->getTitle();
|
|
|
|
|
|
|
|
|
|
$this->getExistingTestPage( $title->getSubpage( 'A' ) );
|
|
|
|
|
$this->getExistingTestPage( $title->getSubpage( 'B' ) );
|
|
|
|
|
|
2022-11-24 22:22:36 +00:00
|
|
|
$this->assertSame( [], $title->getSubpages() );
|
2021-03-22 22:42:20 +00:00
|
|
|
}
|
2021-09-02 12:12:25 +00:00
|
|
|
|
2023-03-23 11:36:19 +00:00
|
|
|
public static function provideNamespaces() {
|
2021-09-02 12:12:25 +00:00
|
|
|
// For ->isExternal() code path, construct a title with interwiki
|
|
|
|
|
$title = Title::makeTitle( NS_FILE, 'test', 'frag', 'meta' );
|
|
|
|
|
return [
|
|
|
|
|
[ NS_MAIN, '' ],
|
|
|
|
|
[ NS_FILE, 'File' ],
|
|
|
|
|
[ NS_MEDIA, 'Media' ],
|
|
|
|
|
[ NS_TALK, 'Talk' ],
|
|
|
|
|
[ NS_CATEGORY, 'Category' ],
|
|
|
|
|
[ $title, 'File' ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getNsText
|
2021-09-07 18:45:21 +00:00
|
|
|
* @dataProvider provideNamespaces
|
2021-09-02 12:12:25 +00:00
|
|
|
*/
|
2021-09-07 18:45:21 +00:00
|
|
|
public function testGetNsText( $namespace, $expected ) {
|
|
|
|
|
if ( $namespace instanceof Title ) {
|
|
|
|
|
$this->assertSame( $expected, $namespace->getNsText() );
|
|
|
|
|
} else {
|
|
|
|
|
$actual = Title::makeTitle( $namespace, 'Title_test' )->getNsText();
|
|
|
|
|
$this->assertSame( $expected, $actual );
|
|
|
|
|
}
|
2021-09-02 12:12:25 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-23 11:36:19 +00:00
|
|
|
public static function providePagesWithSubjects() {
|
2021-09-02 12:12:25 +00:00
|
|
|
return [
|
|
|
|
|
[ Title::makeTitle( NS_USER_TALK, 'User_test' ), 'User' ],
|
|
|
|
|
[ Title::makeTitle( NS_PROJECT, 'Test' ), 'Project' ],
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, 'Test' ), '' ],
|
|
|
|
|
[ Title::makeTitle( NS_CATEGORY, 'Cat_test' ), 'Category' ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getSubjectNsText
|
2021-09-07 18:45:21 +00:00
|
|
|
* @dataProvider providePagesWithSubjects
|
2021-09-02 12:12:25 +00:00
|
|
|
*/
|
2021-09-07 18:45:21 +00:00
|
|
|
public function testGetSubjectNsText( Title $title, $expected ) {
|
|
|
|
|
$actual = $title->getSubjectNsText();
|
2021-09-02 12:12:25 +00:00
|
|
|
$this->assertSame( $expected, $actual );
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-23 11:36:19 +00:00
|
|
|
public static function provideTitlesWithTalkPages() {
|
2021-09-02 12:12:25 +00:00
|
|
|
return [
|
|
|
|
|
[ Title::makeTitle( NS_HELP, 'Help page' ), 'Help_talk' ],
|
|
|
|
|
[ Title::newMainPage(), 'Talk' ],
|
|
|
|
|
[ Title::makeTitle( NS_PROJECT, 'Test' ), 'Project_talk' ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-07 18:45:21 +00:00
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getTalkNsText
|
2021-09-07 18:45:21 +00:00
|
|
|
* @dataProvider provideTitlesWithTalkPages
|
|
|
|
|
*/
|
|
|
|
|
public function testGetTalkNsText( Title $title, $expected ) {
|
|
|
|
|
$actual = $title->getTalkNsText();
|
|
|
|
|
$this->assertSame( $expected, $actual );
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-02 12:12:25 +00:00
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::isSpecial
|
2021-09-02 12:12:25 +00:00
|
|
|
*/
|
|
|
|
|
public function testIsSpecial() {
|
|
|
|
|
$title = Title::makeTitle( NS_SPECIAL, 'Recentchanges/Subpage' );
|
|
|
|
|
$this->assertTrue( $title->isSpecial( 'Recentchanges' ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::isSpecial
|
2021-09-02 12:12:25 +00:00
|
|
|
*/
|
|
|
|
|
public function testIsNotSpecial() {
|
|
|
|
|
$title = Title::newFromText( 'NotSpecialPage/Subpage', NS_SPECIAL );
|
|
|
|
|
$this->assertFalse( $title->isSpecial( 'NotSpecialPage' ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::isTalkPage
|
2021-09-02 12:12:25 +00:00
|
|
|
*/
|
|
|
|
|
public function testIsTalkPage() {
|
|
|
|
|
$title = Title::newFromText( 'Talk page', NS_TALK );
|
|
|
|
|
$this->assertTrue( $title->isTalkPage() );
|
|
|
|
|
|
|
|
|
|
$titleNotInTalkNs = Title::makeTitle( NS_HELP, 'Test' );
|
|
|
|
|
$this->assertFalse( $titleNotInTalkNs->isTalkPage() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getBacklinkCache
|
2021-09-02 12:12:25 +00:00
|
|
|
*/
|
|
|
|
|
public function testGetBacklinkCache() {
|
2021-09-08 22:07:01 +00:00
|
|
|
$blcFactory = $this->getServiceContainer()->getBacklinkCacheFactory();
|
|
|
|
|
$backlinkCache = $blcFactory->getBacklinkCache( Title::makeTitle( NS_FILE, 'Test' ) );
|
|
|
|
|
$this->assertInstanceOf( BacklinkCache::class, $backlinkCache );
|
2021-09-02 12:12:25 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-23 11:36:19 +00:00
|
|
|
public static function provideNsWithSubpagesSupport() {
|
2021-09-07 18:45:21 +00:00
|
|
|
return [
|
|
|
|
|
[ NS_HELP, 'Mainhelp', 'Mainhelp/Subhelp' ],
|
|
|
|
|
[ NS_USER, 'Mainuser', 'Mainuser/Subuser' ],
|
|
|
|
|
[ NS_TALK, 'Maintalk', 'Maintalk/Subtalk' ],
|
|
|
|
|
[ NS_PROJECT, 'Mainproject', 'Mainproject/Subproject' ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-02 12:12:25 +00:00
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::isSubpage
|
|
|
|
|
* @covers MediaWiki\Title\Title::isSubpageOf
|
2021-09-02 12:12:25 +00:00
|
|
|
* @dataProvider provideNsWithSubpagesSupport
|
|
|
|
|
*/
|
|
|
|
|
public function testIsSubpageOfWithNamespacesSubpages( $namespace, $pageName, $subpageName ) {
|
|
|
|
|
$page = Title::makeTitle( $namespace, $pageName, '', 'meta' );
|
|
|
|
|
$subPage = Title::makeTitle( $namespace, $subpageName, '', 'meta' );
|
|
|
|
|
|
|
|
|
|
$this->assertTrue( $subPage->isSubpageOf( $page ) );
|
|
|
|
|
$this->assertTrue( $subPage->isSubpage() );
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-23 11:36:19 +00:00
|
|
|
public static function provideNsWithNoSubpages() {
|
2021-09-02 12:12:25 +00:00
|
|
|
return [
|
2021-09-07 18:45:21 +00:00
|
|
|
[ NS_CATEGORY, 'Maincat', 'Maincat/Subcat' ],
|
|
|
|
|
[ NS_MAIN, 'Mainpage', 'Mainpage/Subpage' ]
|
2021-09-02 12:12:25 +00:00
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::isSubpage
|
|
|
|
|
* @covers MediaWiki\Title\Title::isSubpageOf
|
2021-09-02 12:12:25 +00:00
|
|
|
* @dataProvider provideNsWithNoSubpages
|
|
|
|
|
*/
|
|
|
|
|
public function testIsSubpageOfWithoutNamespacesSubpages( $namespace, $pageName, $subpageName ) {
|
|
|
|
|
$page = Title::makeTitle( $namespace, $pageName, '', 'meta' );
|
|
|
|
|
$subPage = Title::makeTitle( $namespace, $subpageName, '', 'meta' );
|
|
|
|
|
|
|
|
|
|
$this->assertFalse( $page->isSubpageOf( $page ) );
|
|
|
|
|
$this->assertFalse( $subPage->isSubpage() );
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-23 11:36:19 +00:00
|
|
|
public static function provideTitleEditURLs() {
|
2021-09-02 12:12:25 +00:00
|
|
|
return [
|
2021-09-07 18:45:21 +00:00
|
|
|
[ Title::makeTitle( NS_MAIN, 'Title' ), '/w/index.php?title=Title&action=edit' ],
|
|
|
|
|
[ Title::makeTitle( NS_HELP, 'Test', '', 'mw' ), '' ],
|
|
|
|
|
[ Title::makeTitle( NS_HELP, 'Test' ), '/w/index.php?title=Help:Test&action=edit' ],
|
2021-09-02 12:12:25 +00:00
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getEditURL
|
2021-09-02 12:12:25 +00:00
|
|
|
* @dataProvider provideTitleEditURLs
|
|
|
|
|
*/
|
|
|
|
|
public function testGetEditURL( Title $title, $expected ) {
|
|
|
|
|
$actual = $title->getEditURL();
|
|
|
|
|
$this->assertSame( $expected, $actual );
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-23 11:36:19 +00:00
|
|
|
public static function provideTitleEditURLsWithActionPaths() {
|
2021-09-02 12:12:25 +00:00
|
|
|
return [
|
2021-09-07 18:45:21 +00:00
|
|
|
[ Title::newFromText( 'Title', NS_MAIN ), '/wiki/edit/Title' ],
|
2021-09-02 12:12:25 +00:00
|
|
|
[ Title::makeTitle( NS_HELP, 'Test', '', 'mw' ), '' ],
|
2021-09-07 18:45:21 +00:00
|
|
|
[ Title::newFromText( 'Test', NS_HELP ), '/wiki/edit/Help:Test' ],
|
2021-09-02 12:12:25 +00:00
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getEditURL
|
2021-09-02 12:12:25 +00:00
|
|
|
* @dataProvider provideTitleEditURLsWithActionPaths
|
|
|
|
|
*/
|
|
|
|
|
public function testGetEditUrlWithActionPaths( Title $title, $expected ) {
|
2022-07-06 15:05:30 +00:00
|
|
|
$this->overrideConfigValue( MainConfigNames::ActionPaths, [ 'edit' => '/wiki/edit/$1' ] );
|
2021-09-02 12:12:25 +00:00
|
|
|
$actual = $title->getEditURL();
|
|
|
|
|
$this->assertSame( $expected, $actual );
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-03 13:10:28 +00:00
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::isMainPage
|
|
|
|
|
* @covers MediaWiki\Title\Title::equals
|
2021-09-03 13:10:28 +00:00
|
|
|
*/
|
|
|
|
|
public function testIsMainPage() {
|
|
|
|
|
$this->assertTrue( Title::newMainPage()->isMainPage() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::isMainPage
|
|
|
|
|
* @covers MediaWiki\Title\Title::equals
|
2021-09-03 13:10:28 +00:00
|
|
|
* @dataProvider provideMainPageTitles
|
|
|
|
|
*/
|
|
|
|
|
public function testIsNotMainPage( Title $title, $expected ) {
|
2022-02-08 05:12:43 +00:00
|
|
|
$this->assertSame( $expected, $title->isMainPage() );
|
2021-09-03 13:10:28 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-23 11:36:19 +00:00
|
|
|
public static function provideMainPageTitles() {
|
2021-09-03 13:10:28 +00:00
|
|
|
return [
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, 'Test' ), false ],
|
|
|
|
|
[ Title::makeTitle( NS_CATEGORY, 'mw:Category' ), false ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getPrefixedURL
|
|
|
|
|
* @covers MediaWiki\Title\Title::prefix
|
2021-09-03 13:10:28 +00:00
|
|
|
* @dataProvider provideDataForTestGetPrefixedURL
|
|
|
|
|
*/
|
|
|
|
|
public function testGetPrefixedURL( Title $title, $expected ) {
|
|
|
|
|
$actual = $title->getPrefixedURL();
|
|
|
|
|
|
|
|
|
|
$this->assertSame( $expected, $actual );
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-23 11:36:19 +00:00
|
|
|
public static function provideDataForTestGetPrefixedURL() {
|
2021-09-03 13:10:28 +00:00
|
|
|
return [
|
|
|
|
|
[ Title::makeTitle( NS_FILE, 'Title' ), 'File:Title' ],
|
|
|
|
|
[ Title::makeTitle( NS_MEDIA, 'Title' ), 'Media:Title' ],
|
|
|
|
|
[ Title::makeTitle( NS_CATEGORY, 'Title' ), 'Category:Title' ],
|
|
|
|
|
[ Title::makeTitle( NS_FILE, 'Title with spaces' ), 'File:Title_with_spaces' ],
|
|
|
|
|
[
|
|
|
|
|
Title::makeTitle( NS_FILE, 'Title with spaces', '', 'mw' ),
|
|
|
|
|
'mw:File:Title_with_spaces'
|
|
|
|
|
],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::__toString
|
2021-09-03 13:10:28 +00:00
|
|
|
*/
|
|
|
|
|
public function testToString() {
|
|
|
|
|
$title = Title::makeTitle( NS_USER, 'User test' );
|
|
|
|
|
|
|
|
|
|
$this->assertSame( 'User:User test', (string)$title );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getFullText
|
2021-09-03 13:10:28 +00:00
|
|
|
* @dataProvider provideDataForTestGetFullText
|
|
|
|
|
*/
|
|
|
|
|
public function testGetFullText( Title $title, $expected ) {
|
|
|
|
|
$actual = $title->getFullText();
|
|
|
|
|
|
|
|
|
|
$this->assertSame( $expected, $actual );
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-23 11:36:19 +00:00
|
|
|
public static function provideDataForTestGetFullText() {
|
2021-09-03 13:10:28 +00:00
|
|
|
return [
|
|
|
|
|
[ Title::makeTitle( NS_TALK, 'Test' ), 'Talk:Test' ],
|
|
|
|
|
[ Title::makeTitle( NS_HELP, 'Test', 'frag' ), 'Help:Test#frag' ],
|
|
|
|
|
[ Title::makeTitle( NS_TALK, 'Test', 'frag', 'phab' ), 'phab:Talk:Test#frag' ],
|
|
|
|
|
];
|
|
|
|
|
}
|
2021-09-07 18:45:21 +00:00
|
|
|
|
2023-03-23 11:36:19 +00:00
|
|
|
public static function provideIsSamePageAs() {
|
2021-09-17 15:56:30 +00:00
|
|
|
$title = Title::makeTitle( 0, 'Foo' );
|
|
|
|
|
$title->resetArticleID( 1 );
|
|
|
|
|
yield '(PageIdentityValue) same text, title has ID 0' => [
|
|
|
|
|
$title,
|
|
|
|
|
new PageIdentityValue( 1, 0, 'Foo', PageIdentity::LOCAL ),
|
|
|
|
|
true
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
$title = Title::makeTitle( 1, 'Bar_Baz' );
|
|
|
|
|
$title->resetArticleID( 0 );
|
|
|
|
|
yield '(PageIdentityValue) same text, PageIdentityValue has ID 0' => [
|
|
|
|
|
$title,
|
|
|
|
|
new PageIdentityValue( 0, 1, 'Bar_Baz', PageIdentity::LOCAL ),
|
|
|
|
|
true
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
$title = Title::makeTitle( 0, 'Foo' );
|
|
|
|
|
$title->resetArticleID( 0 );
|
|
|
|
|
yield '(PageIdentityValue) different text, both IDs are 0' => [
|
|
|
|
|
$title,
|
|
|
|
|
new PageIdentityValue( 0, 0, 'Foozz', PageIdentity::LOCAL ),
|
|
|
|
|
false
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
$title = Title::makeTitle( 0, 'Foo' );
|
|
|
|
|
$title->resetArticleID( 0 );
|
|
|
|
|
yield '(PageIdentityValue) different namespace' => [
|
|
|
|
|
$title,
|
|
|
|
|
new PageIdentityValue( 0, 1, 'Foo', PageIdentity::LOCAL ),
|
|
|
|
|
false
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
$title = Title::makeTitle( 0, 'Foo', '' );
|
|
|
|
|
$title->resetArticleID( 1 );
|
|
|
|
|
yield '(PageIdentityValue) different wiki, different ID' => [
|
|
|
|
|
$title,
|
|
|
|
|
new PageIdentityValue( 1, 0, 'Foo', 'bar' ),
|
|
|
|
|
false
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
$title = Title::makeTitle( 0, 'Foo', '' );
|
|
|
|
|
$title->resetArticleID( 0 );
|
|
|
|
|
yield '(PageIdentityValue) different wiki, both IDs are 0' => [
|
|
|
|
|
$title,
|
|
|
|
|
new PageIdentityValue( 0, 0, 'Foo', 'bar' ),
|
|
|
|
|
false
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::isSamePageAs
|
2021-09-17 15:56:30 +00:00
|
|
|
* @dataProvider provideIsSamePageAs
|
|
|
|
|
*/
|
|
|
|
|
public function testIsSamePageAs( Title $firstValue, $secondValue, $expectedSame ) {
|
|
|
|
|
$this->assertSame(
|
|
|
|
|
$expectedSame,
|
|
|
|
|
$firstValue->isSamePageAs( $secondValue )
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-02 16:08:42 +00:00
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getArticleID
|
|
|
|
|
* @covers MediaWiki\Title\Title::getId
|
|
|
|
|
* @covers MediaWiki\Title\Title::getLength
|
|
|
|
|
* @covers MediaWiki\Title\Title::getLatestRevID
|
|
|
|
|
* @covers MediaWiki\Title\Title::exists
|
|
|
|
|
* @covers MediaWiki\Title\Title::isNewPage
|
|
|
|
|
* @covers MediaWiki\Title\Title::isRedirect
|
|
|
|
|
* @covers MediaWiki\Title\Title::getTouched
|
|
|
|
|
* @covers MediaWiki\Title\Title::getContentModel
|
|
|
|
|
* @covers MediaWiki\Title\Title::getFieldFromPageStore
|
2022-03-02 16:08:42 +00:00
|
|
|
*/
|
|
|
|
|
public function testGetFieldsOfNonExistingPage() {
|
|
|
|
|
$title = Title::makeTitle( NS_MAIN, 'ThisDoesNotExist-92347852349' );
|
|
|
|
|
|
|
|
|
|
$this->assertSame( 0, $title->getArticleID() );
|
|
|
|
|
$this->assertSame( 0, $title->getId() );
|
|
|
|
|
$this->assertSame( 0, $title->getLength() );
|
|
|
|
|
$this->assertSame( 0, $title->getLatestRevID() );
|
|
|
|
|
$this->assertFalse( $title->exists() );
|
|
|
|
|
$this->assertFalse( $title->isNewPage() );
|
|
|
|
|
$this->assertFalse( $title->isRedirect() );
|
|
|
|
|
$this->assertFalse( $title->getTouched() );
|
|
|
|
|
$this->assertNotEmpty( $title->getContentModel() );
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-14 13:23:43 +00:00
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getDefaultSystemMessage
|
2022-11-14 13:23:43 +00:00
|
|
|
*/
|
|
|
|
|
public function testGetDefaultSystemMessage() {
|
|
|
|
|
$title = Title::makeTitle( NS_MEDIAWIKI, 'Logouttext' );
|
|
|
|
|
|
|
|
|
|
$this->assertInstanceOf( Message::class, $title->getDefaultSystemMessage() );
|
|
|
|
|
$this->assertStringContainsString( 'You are now logged out', $title->getDefaultMessageText() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2023-05-27 09:43:12 +00:00
|
|
|
* @covers MediaWiki\Title\Title::getDefaultSystemMessage
|
2022-11-14 13:23:43 +00:00
|
|
|
*/
|
|
|
|
|
public function testGetDefaultSystemMessageReturnsNull() {
|
|
|
|
|
$title = Title::makeTitle( NS_MAIN, 'Some title' );
|
|
|
|
|
|
|
|
|
|
$this->assertNull( $title->getDefaultSystemMessage() );
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-14 16:26:35 +00:00
|
|
|
}
|