2011-11-22 13:34:55 +00:00
|
|
|
<?php
|
|
|
|
|
|
2019-01-23 10:17:21 +00:00
|
|
|
use MediaWiki\Interwiki\InterwikiLookup;
|
2018-06-11 06:55:11 +00:00
|
|
|
use MediaWiki\MediaWikiServices;
|
2020-12-03 08:52:55 +00:00
|
|
|
use Wikimedia\Assert\PreconditionException;
|
2018-06-11 06:55:11 +00:00
|
|
|
|
2012-05-13 22:02:29 +00:00
|
|
|
/**
|
|
|
|
|
* @group ContentHandler
|
2012-12-09 09:27:56 +00:00
|
|
|
* @group Database
|
2012-09-19 18:07:56 +00:00
|
|
|
*
|
2014-07-24 09:30:25 +00:00
|
|
|
* @note We don't make assumptions about the main namespace.
|
|
|
|
|
* But we do expect the Help namespace to contain Wikitext.
|
2012-05-13 22:02:29 +00:00
|
|
|
*/
|
2014-12-30 09:22:56 +00:00
|
|
|
class TitleMethodsTest extends MediaWikiLangTestCase {
|
2011-11-22 13:34:55 +00:00
|
|
|
|
2019-10-20 18:11:08 +00:00
|
|
|
protected function setUp() : void {
|
2012-10-23 17:02:36 +00:00
|
|
|
parent::setUp();
|
|
|
|
|
|
2012-10-09 09:34:24 +00:00
|
|
|
$this->mergeMwGlobalArrayValue(
|
|
|
|
|
'wgExtraNamespaces',
|
2016-02-17 09:09:32 +00:00
|
|
|
[
|
2012-10-09 09:34:24 +00:00
|
|
|
12302 => 'TEST-JS',
|
|
|
|
|
12303 => 'TEST-JS_TALK',
|
2016-02-17 09:09:32 +00:00
|
|
|
]
|
2012-10-09 09:34:24 +00:00
|
|
|
);
|
2012-04-19 10:55:46 +00:00
|
|
|
|
2012-10-09 09:34:24 +00:00
|
|
|
$this->mergeMwGlobalArrayValue(
|
|
|
|
|
'wgNamespaceContentModels',
|
2016-02-17 09:09:32 +00:00
|
|
|
[
|
2012-10-09 09:34:24 +00:00
|
|
|
12302 => CONTENT_MODEL_JAVASCRIPT,
|
2016-02-17 09:09:32 +00:00
|
|
|
]
|
2012-10-09 09:34:24 +00:00
|
|
|
);
|
2012-04-26 10:11:34 +00:00
|
|
|
}
|
2012-04-19 10:55:46 +00:00
|
|
|
|
2020-12-23 10:03:34 +00:00
|
|
|
protected function tearDown() : void {
|
|
|
|
|
Title::clearCaches();
|
|
|
|
|
parent::tearDown();
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-08 10:56:20 +00:00
|
|
|
public static function provideInNamespace() {
|
2016-02-17 09:09:32 +00:00
|
|
|
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 ],
|
|
|
|
|
];
|
2011-11-22 13:34:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2012-10-08 10:56:20 +00:00
|
|
|
* @dataProvider provideInNamespace
|
2013-10-21 21:09:13 +00:00
|
|
|
* @covers Title::inNamespace
|
2011-11-22 13:34:55 +00:00
|
|
|
*/
|
|
|
|
|
public function testInNamespace( $title, $ns, $expectedBool ) {
|
|
|
|
|
$title = Title::newFromText( $title );
|
2012-05-02 17:30:09 +00:00
|
|
|
$this->assertEquals( $expectedBool, $title->inNamespace( $ns ) );
|
2011-11-22 13:34:55 +00:00
|
|
|
}
|
|
|
|
|
|
2013-10-21 21:09:13 +00:00
|
|
|
/**
|
|
|
|
|
* @covers Title::inNamespaces
|
|
|
|
|
*/
|
2011-11-22 13:34:55 +00:00
|
|
|
public function testInNamespaces() {
|
|
|
|
|
$mainpage = Title::newFromText( 'Main Page' );
|
|
|
|
|
$this->assertTrue( $mainpage->inNamespaces( NS_MAIN, NS_USER ) );
|
2016-02-17 09:09:32 +00:00
|
|
|
$this->assertTrue( $mainpage->inNamespaces( [ NS_MAIN, NS_USER ] ) );
|
|
|
|
|
$this->assertTrue( $mainpage->inNamespaces( [ NS_USER, NS_MAIN ] ) );
|
|
|
|
|
$this->assertFalse( $mainpage->inNamespaces( [ NS_PROJECT, NS_TEMPLATE ] ) );
|
2011-11-22 13:34:55 +00:00
|
|
|
}
|
|
|
|
|
|
2012-10-08 10:56:20 +00:00
|
|
|
public static function provideHasSubjectNamespace() {
|
2016-02-17 09:09:32 +00:00
|
|
|
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 ],
|
|
|
|
|
];
|
2011-11-22 13:34:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2012-10-08 10:56:20 +00:00
|
|
|
* @dataProvider provideHasSubjectNamespace
|
2013-10-21 21:09:13 +00:00
|
|
|
* @covers Title::hasSubjectNamespace
|
2011-11-22 13:34:55 +00:00
|
|
|
*/
|
|
|
|
|
public function testHasSubjectNamespace( $title, $ns, $expectedBool ) {
|
|
|
|
|
$title = Title::newFromText( $title );
|
assertEquals is $expected, $actual, not $actual, $expected
Fix Title related tests that are the wrong way round (noticed by Daniel Kinzler
when creating more tests, and wondering why phpunit was making error messages
that didn't make any sense!)
public static function assertEquals($expected, $actual, $message = '',
$delta = 0, $maxDepth = 10, $canonicalize = FALSE, $ignoreCase = FALSE)
Change-Id: I09aeb7cb7edb8e486ccf2f54673f91cd9704cd3b
2012-04-18 12:50:39 +00:00
|
|
|
$this->assertEquals( $expectedBool, $title->hasSubjectNamespace( $ns ) );
|
2011-11-22 13:34:55 +00:00
|
|
|
}
|
|
|
|
|
|
2012-05-13 22:02:29 +00:00
|
|
|
public function dataGetContentModel() {
|
2016-02-17 09:09:32 +00:00
|
|
|
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 ],
|
|
|
|
|
];
|
2012-04-26 10:11:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2012-05-13 22:02:29 +00:00
|
|
|
* @dataProvider dataGetContentModel
|
2013-10-21 21:09:13 +00:00
|
|
|
* @covers Title::getContentModel
|
2012-04-26 10:11:34 +00:00
|
|
|
*/
|
2012-05-13 22:02:29 +00:00
|
|
|
public function testGetContentModel( $title, $expectedModelId ) {
|
2012-04-26 10:11:34 +00:00
|
|
|
$title = Title::newFromText( $title );
|
2012-05-13 22:02:29 +00:00
|
|
|
$this->assertEquals( $expectedModelId, $title->getContentModel() );
|
2012-04-26 10:11:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2012-05-13 22:02:29 +00:00
|
|
|
* @dataProvider dataGetContentModel
|
2013-10-21 21:09:13 +00:00
|
|
|
* @covers Title::hasContentModel
|
2012-04-26 10:11:34 +00:00
|
|
|
*/
|
2012-05-13 22:02:29 +00:00
|
|
|
public function testHasContentModel( $title, $expectedModelId ) {
|
2012-04-26 10:11:34 +00:00
|
|
|
$title = Title::newFromText( $title );
|
2012-05-13 22:02:29 +00:00
|
|
|
$this->assertTrue( $title->hasContentModel( $expectedModelId ) );
|
2012-04-26 10:11:34 +00:00
|
|
|
}
|
|
|
|
|
|
2018-02-13 00:15:30 +00:00
|
|
|
public static function provideIsSiteConfigPage() {
|
2016-02-17 09:09:32 +00:00
|
|
|
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 ],
|
2018-02-13 00:20:05 +00:00
|
|
|
[ 'User:Foo/bar.json', false ],
|
2016-02-17 09:09:32 +00:00
|
|
|
[ 'User:Foo/bar.css', false ],
|
2018-02-13 00:15:30 +00:00
|
|
|
[ 'User:Foo/bar.JS', false ],
|
2018-02-13 00:20:05 +00:00
|
|
|
[ 'User:Foo/bar.JSON', false ],
|
2018-02-13 00:15:30 +00:00
|
|
|
[ 'User:Foo/bar.CSS', false ],
|
2016-02-17 09:09:32 +00:00
|
|
|
[ 'User talk:Foo/bar.css', false ],
|
|
|
|
|
[ 'User:Foo/bar.js.xxx', false ],
|
|
|
|
|
[ 'User:Foo/bar.xxx', false ],
|
2021-03-02 00:34:54 +00:00
|
|
|
[ 'MediaWiki:Foo.js', 'javascript' ],
|
|
|
|
|
[ 'MediaWiki:Foo.json', 'json' ],
|
|
|
|
|
[ 'MediaWiki:Foo.css', 'css' ],
|
2016-02-17 09:09:32 +00:00
|
|
|
[ 'MediaWiki:Foo.JS', false ],
|
2018-02-13 00:20:05 +00:00
|
|
|
[ 'MediaWiki:Foo.JSON', false ],
|
2016-02-17 09:09:32 +00:00
|
|
|
[ 'MediaWiki:Foo.CSS', false ],
|
2021-03-02 00:34:54 +00:00
|
|
|
[ 'MediaWiki:Foo/bar.css', 'css' ],
|
2016-02-17 09:09:32 +00:00
|
|
|
[ 'MediaWiki:Foo.css.xxx', false ],
|
|
|
|
|
[ 'TEST-JS:Foo', false ],
|
|
|
|
|
[ 'TEST-JS:Foo.js', false ],
|
|
|
|
|
];
|
2012-05-02 17:30:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2018-02-13 00:15:30 +00:00
|
|
|
* @dataProvider provideIsSiteConfigPage
|
|
|
|
|
* @covers Title::isSiteConfigPage
|
2021-03-02 00:34:54 +00:00
|
|
|
* @covers Title::isSiteJsConfigPage
|
|
|
|
|
* @covers Title::isSiteJsonConfigPage
|
|
|
|
|
* @covers Title::isSiteCssConfigPage
|
2012-05-02 17:30:09 +00:00
|
|
|
*/
|
2021-03-02 00:34:54 +00:00
|
|
|
public function testSiteConfigPage( $title, $expected ) {
|
2012-05-02 17:30:09 +00:00
|
|
|
$title = Title::newFromText( $title );
|
2021-03-02 00:34:54 +00:00
|
|
|
|
|
|
|
|
// $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()
|
|
|
|
|
);
|
2012-05-02 17:30:09 +00:00
|
|
|
}
|
|
|
|
|
|
2019-03-26 10:58:54 +00:00
|
|
|
public function provideGetSkinFromConfigSubpage() {
|
|
|
|
|
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
|
|
|
|
|
* @covers Title::getSkinFromConfigSubpage
|
|
|
|
|
*/
|
|
|
|
|
public function testGetSkinFromConfigSubpage( $title, $expected ) {
|
|
|
|
|
$title = Title::newFromText( $title );
|
|
|
|
|
$this->assertSame( $expected, $title->getSkinFromConfigSubpage() );
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-13 00:15:30 +00:00
|
|
|
public static function provideIsUserConfigPage() {
|
2016-02-17 09:09:32 +00:00
|
|
|
return [
|
|
|
|
|
[ 'Help:Foo', false ],
|
|
|
|
|
[ 'Help:Foo.js', false ],
|
|
|
|
|
[ 'Help:Foo/bar.js', false ],
|
|
|
|
|
[ 'User:Foo', false ],
|
|
|
|
|
[ 'User:Foo.js', false ],
|
2021-03-02 00:34:54 +00:00
|
|
|
[ 'User:Foo/bar.js', 'javascript' ],
|
2018-02-13 00:15:30 +00:00
|
|
|
[ 'User:Foo/bar.JS', false ],
|
2021-03-02 00:34:54 +00:00
|
|
|
[ 'User:Foo/bar.json', 'json' ],
|
2018-02-13 00:20:05 +00:00
|
|
|
[ 'User:Foo/bar.JSON', false ],
|
2021-03-02 00:34:54 +00:00
|
|
|
[ 'User:Foo/bar.css', 'css' ],
|
2018-02-13 00:15:30 +00:00
|
|
|
[ 'User:Foo/bar.CSS', false ],
|
2016-02-17 09:09:32 +00:00
|
|
|
[ 'User talk:Foo/bar.css', false ],
|
|
|
|
|
[ 'User:Foo/bar.js.xxx', false ],
|
|
|
|
|
[ 'User:Foo/bar.xxx', false ],
|
|
|
|
|
[ 'MediaWiki:Foo.js', false ],
|
2018-02-13 00:20:05 +00:00
|
|
|
[ 'MediaWiki:Foo.json', false ],
|
2018-02-13 00:15:30 +00:00
|
|
|
[ 'MediaWiki:Foo.css', false ],
|
|
|
|
|
[ 'MediaWiki:Foo.JS', false ],
|
2018-02-13 00:20:05 +00:00
|
|
|
[ 'MediaWiki:Foo.JSON', false ],
|
2018-02-13 00:15:30 +00:00
|
|
|
[ 'MediaWiki:Foo.CSS', false ],
|
|
|
|
|
[ 'MediaWiki:Foo.css.xxx', false ],
|
2016-02-17 09:09:32 +00:00
|
|
|
[ 'TEST-JS:Foo', false ],
|
|
|
|
|
[ 'TEST-JS:Foo.js', false ],
|
|
|
|
|
];
|
2012-05-02 17:30:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2018-02-13 00:15:30 +00:00
|
|
|
* @dataProvider provideIsUserConfigPage
|
|
|
|
|
* @covers Title::isUserConfigPage
|
2021-03-02 00:34:54 +00:00
|
|
|
* @covers Title::isUserJsConfigPage
|
|
|
|
|
* @covers Title::isUserJsonConfigPage
|
2018-02-13 00:15:30 +00:00
|
|
|
* @covers Title::isUserCssConfigPage
|
2012-05-02 17:30:09 +00:00
|
|
|
*/
|
2021-03-02 00:34:54 +00:00
|
|
|
public function testIsUserConfigPage( $title, $expected ) {
|
2012-05-02 17:30:09 +00:00
|
|
|
$title = Title::newFromText( $title );
|
|
|
|
|
|
2021-03-02 00:34:54 +00:00
|
|
|
// $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()
|
|
|
|
|
);
|
2012-05-02 17:30:09 +00:00
|
|
|
}
|
|
|
|
|
|
2012-10-08 10:56:20 +00:00
|
|
|
public static function provideIsWikitextPage() {
|
2016-02-17 09:09:32 +00:00
|
|
|
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 ],
|
2018-02-13 00:20:05 +00:00
|
|
|
[ 'User:Foo/bar.json', false ],
|
2016-02-17 09:09:32 +00:00
|
|
|
[ '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 ],
|
2018-02-13 00:20:05 +00:00
|
|
|
[ 'User:Foo/bar.JSON', true ],
|
2016-02-17 09:09:32 +00:00
|
|
|
[ 'User:Foo/bar.CSS', true ],
|
2018-02-13 00:20:05 +00:00
|
|
|
[ 'MediaWiki:Foo.json', false ],
|
2018-02-13 00:15:30 +00:00
|
|
|
[ 'MediaWiki:Foo.css', false ],
|
|
|
|
|
[ 'MediaWiki:Foo.JS', true ],
|
2018-02-13 00:20:05 +00:00
|
|
|
[ 'MediaWiki:Foo.JSON', true ],
|
2018-02-13 00:15:30 +00:00
|
|
|
[ 'MediaWiki:Foo.CSS', true ],
|
|
|
|
|
[ 'MediaWiki:Foo.css.xxx', true ],
|
2016-02-17 09:09:32 +00:00
|
|
|
[ 'TEST-JS:Foo', false ],
|
|
|
|
|
[ 'TEST-JS:Foo.js', false ],
|
|
|
|
|
];
|
2012-05-02 17:30:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2012-10-08 10:56:20 +00:00
|
|
|
* @dataProvider provideIsWikitextPage
|
2013-10-21 21:09:13 +00:00
|
|
|
* @covers Title::isWikitextPage
|
2012-05-02 17:30:09 +00:00
|
|
|
*/
|
|
|
|
|
public function testIsWikitextPage( $title, $expectedBool ) {
|
|
|
|
|
$title = Title::newFromText( $title );
|
|
|
|
|
$this->assertEquals( $expectedBool, $title->isWikitextPage() );
|
|
|
|
|
}
|
2014-12-05 01:45:05 +00:00
|
|
|
|
|
|
|
|
public static function provideGetOtherPage() {
|
2016-02-17 09:09:32 +00:00
|
|
|
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 ],
|
2017-08-29 19:53:53 +00:00
|
|
|
[ 'Media:File.jpg', null ],
|
2016-02-17 09:09:32 +00:00
|
|
|
];
|
2014-12-05 01:45:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideGetOtherpage
|
|
|
|
|
* @covers Title::getOtherPage
|
|
|
|
|
*
|
|
|
|
|
* @param string $text
|
|
|
|
|
* @param string|null $expected
|
|
|
|
|
*/
|
|
|
|
|
public function testGetOtherPage( $text, $expected ) {
|
|
|
|
|
if ( $expected === null ) {
|
2019-10-05 22:14:35 +00:00
|
|
|
$this->expectException( MWException::class );
|
2014-12-05 01:45:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$title = Title::newFromText( $text );
|
|
|
|
|
$this->assertEquals( $expected, $title->getOtherPage()->getPrefixedText() );
|
|
|
|
|
}
|
2015-05-24 15:50:24 +00:00
|
|
|
|
2017-12-25 07:28:03 +00:00
|
|
|
/**
|
|
|
|
|
* @covers Title::clearCaches
|
|
|
|
|
*/
|
2015-05-24 15:50:24 +00:00
|
|
|
public function testClearCaches() {
|
2018-06-11 06:55:11 +00:00
|
|
|
$linkCache = MediaWikiServices::getInstance()->getLinkCache();
|
2015-05-24 15:50:24 +00:00
|
|
|
|
|
|
|
|
$title1 = Title::newFromText( 'Foo' );
|
|
|
|
|
$linkCache->addGoodLinkObj( 23, $title1 );
|
|
|
|
|
|
|
|
|
|
Title::clearCaches();
|
|
|
|
|
|
|
|
|
|
$title2 = Title::newFromText( 'Foo' );
|
|
|
|
|
$this->assertNotSame( $title1, $title2, 'title cache should be empty' );
|
2019-09-17 14:31:49 +00:00
|
|
|
$this->assertSame( 0, $linkCache->getGoodLinkID( 'Foo' ), 'link cache should be empty' );
|
2015-05-24 15:50:24 +00:00
|
|
|
}
|
2018-10-25 04:31:58 +00:00
|
|
|
|
2019-01-23 10:17:21 +00:00
|
|
|
public function provideGetLinkURL() {
|
|
|
|
|
yield 'Simple' => [
|
|
|
|
|
'/wiki/Goats',
|
|
|
|
|
NS_MAIN,
|
|
|
|
|
'Goats'
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
yield 'Fragment' => [
|
|
|
|
|
'/wiki/Goats#Goatificatiön',
|
|
|
|
|
NS_MAIN,
|
|
|
|
|
'Goats',
|
|
|
|
|
'Goatificatiön'
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
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'
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-19 14:27:22 +00:00
|
|
|
private function installFakeInterwikiLookup() {
|
|
|
|
|
$interwikiLookup =
|
|
|
|
|
$this->createNoOpMock( InterwikiLookup::class, [ 'fetch', 'isValidInterwiki' ] );
|
|
|
|
|
|
|
|
|
|
$interwikis = [
|
|
|
|
|
'' => null,
|
|
|
|
|
'acme' => new Interwiki(
|
|
|
|
|
'acme',
|
|
|
|
|
'https://acme.test/$1'
|
|
|
|
|
),
|
|
|
|
|
'yy' => new Interwiki(
|
|
|
|
|
'yy',
|
|
|
|
|
'https://yy.wiki.test/wiki/$1',
|
|
|
|
|
'/w/api.php',
|
|
|
|
|
'yywiki',
|
|
|
|
|
true
|
|
|
|
|
),
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
$interwikiLookup->method( 'fetch' )
|
2021-02-07 13:10:36 +00:00
|
|
|
->willReturnCallback( static function ( $interwiki ) use ( $interwikis ) {
|
2021-01-19 14:27:22 +00:00
|
|
|
return $interwikis[$interwiki] ?? false;
|
|
|
|
|
} );
|
|
|
|
|
|
|
|
|
|
$interwikiLookup->method( 'isValidInterwiki' )
|
2021-02-07 13:10:36 +00:00
|
|
|
->willReturnCallback( static function ( $interwiki ) use ( $interwikis ) {
|
2021-01-19 14:27:22 +00:00
|
|
|
return isset( $interwikis[$interwiki] );
|
|
|
|
|
} );
|
|
|
|
|
|
|
|
|
|
$this->setService( 'InterwikiLookup', $interwikiLookup );
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-23 10:17:21 +00:00
|
|
|
/**
|
|
|
|
|
* @dataProvider provideGetLinkURL
|
|
|
|
|
*
|
|
|
|
|
* @covers Title::getLinkURL
|
|
|
|
|
* @covers Title::getFullURL
|
|
|
|
|
* @covers Title::getLocalURL
|
|
|
|
|
* @covers Title::getFragmentForURL
|
|
|
|
|
*/
|
|
|
|
|
public function testGetLinkURL(
|
|
|
|
|
$expected,
|
|
|
|
|
$ns,
|
|
|
|
|
$title,
|
|
|
|
|
$fragment = '',
|
|
|
|
|
$interwiki = '',
|
|
|
|
|
$query = '',
|
|
|
|
|
$query2 = false,
|
|
|
|
|
$proto = false
|
|
|
|
|
) {
|
|
|
|
|
$this->setMwGlobals( [
|
|
|
|
|
'wgServer' => 'https://xx.wiki.test',
|
|
|
|
|
'wgArticlePath' => '/wiki/$1',
|
|
|
|
|
'wgExternalInterwikiFragmentMode' => 'legacy',
|
|
|
|
|
'wgFragmentMode' => [ 'html5', 'legacy' ]
|
|
|
|
|
] );
|
|
|
|
|
|
2021-01-19 14:27:22 +00:00
|
|
|
$this->installFakeInterwikiLookup();
|
2019-01-23 10:17:21 +00:00
|
|
|
|
|
|
|
|
$title = Title::makeTitle( $ns, $title, $fragment, $interwiki );
|
|
|
|
|
$this->assertSame( $expected, $title->getLinkURL( $query, $query2, $proto ) );
|
|
|
|
|
}
|
2020-12-03 08:52:55 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers Title::getWikiId
|
|
|
|
|
*/
|
|
|
|
|
public function testGetWikiId() {
|
|
|
|
|
$title = Title::newFromText( 'Foo' );
|
|
|
|
|
$this->assertFalse( $title->getWikiId() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function provideProperPage() {
|
|
|
|
|
return [
|
|
|
|
|
[ NS_MAIN, 'Test' ],
|
|
|
|
|
[ NS_MAIN, 'User' ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideProperPage
|
|
|
|
|
* @covers Title::toPageIdentity
|
|
|
|
|
*/
|
|
|
|
|
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() );
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-16 16:39:15 +00:00
|
|
|
/**
|
|
|
|
|
* @dataProvider provideProperPage
|
|
|
|
|
* @covers Title::toPageRecord
|
|
|
|
|
*/
|
|
|
|
|
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() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideImproperPage
|
|
|
|
|
* @covers Title::toPageRecord
|
|
|
|
|
*/
|
|
|
|
|
public function testToPageRecord_fail( $ns, $text, $fragment = '', $interwiki = '' ) {
|
|
|
|
|
$title = Title::makeTitle( $ns, $text, $fragment, $interwiki );
|
|
|
|
|
|
|
|
|
|
$this->expectException( PreconditionException::class );
|
|
|
|
|
$title->toPageRecord();
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-03 08:52:55 +00:00
|
|
|
public function provideImproperPage() {
|
|
|
|
|
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' ],
|
|
|
|
|
|
|
|
|
|
// Can exist but include a fragment
|
|
|
|
|
[ NS_MAIN, 'Foo', 'bar' ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideImproperPage
|
|
|
|
|
* @covers Title::getId
|
|
|
|
|
*/
|
|
|
|
|
public function testGetId_fail( $ns, $text, $fragment = '', $interwiki = '' ) {
|
|
|
|
|
$title = Title::makeTitle( $ns, $text, $fragment, $interwiki );
|
|
|
|
|
|
|
|
|
|
$this->expectException( PreconditionException::class );
|
|
|
|
|
$title->getId();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideImproperPage
|
|
|
|
|
* @covers Title::toPageIdentity
|
|
|
|
|
*/
|
|
|
|
|
public function testToPageIdentity_fail( $ns, $text, $fragment = '', $interwiki = '' ) {
|
|
|
|
|
$title = Title::makeTitle( $ns, $text, $fragment, $interwiki );
|
|
|
|
|
|
|
|
|
|
$this->expectException( PreconditionException::class );
|
|
|
|
|
$title->toPageIdentity();
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-19 14:27:22 +00:00
|
|
|
public function provideMakeTitle() {
|
|
|
|
|
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
|
|
|
|
|
* @covers Title::makeTitle
|
|
|
|
|
*/
|
|
|
|
|
public function testMakeTitle( $expected, $ns, $text, $fragment = '', $interwiki = '' ) {
|
|
|
|
|
$this->installFakeInterwikiLookup();
|
|
|
|
|
$title = Title::makeTitle( $ns, $text, $fragment, $interwiki );
|
|
|
|
|
|
|
|
|
|
$this->assertTrue( $title->isValid() );
|
|
|
|
|
$this->assertSame( $expected, $title->getFullText() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function provideMakeTitle_invalid() {
|
|
|
|
|
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' ];
|
|
|
|
|
|
|
|
|
|
// Is the trailing # intentional?
|
|
|
|
|
yield 'bad interwiki' => [ 'qwerty:Foo#', NS_MAIN, 'Foo', null, 'qwerty' ];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideMakeTitle_invalid
|
|
|
|
|
* @covers Title::makeTitle
|
|
|
|
|
*/
|
|
|
|
|
public function testMakeTitle_invalid( $expected, $ns, $text, $fragment = '', $interwiki = '' ) {
|
|
|
|
|
$this->installFakeInterwikiLookup();
|
|
|
|
|
$title = Title::makeTitle( $ns, $text, $fragment, $interwiki );
|
|
|
|
|
|
|
|
|
|
$this->assertFalse( $title->isValid() );
|
|
|
|
|
$this->assertSame( $expected, $title->getFullText() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function provideMakeTitleSafe() {
|
|
|
|
|
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
|
|
|
|
|
* @covers Title::makeTitleSafe
|
|
|
|
|
*/
|
|
|
|
|
public function testMakeTitleSafe( $expected, $ns, $text, $fragment = '', $interwiki = '' ) {
|
|
|
|
|
$this->installFakeInterwikiLookup();
|
|
|
|
|
$title = Title::makeTitleSafe( $ns, $text, $fragment, $interwiki );
|
|
|
|
|
|
|
|
|
|
$this->assertTrue( $title->isValid() );
|
|
|
|
|
$this->assertSame( $expected, $title->getFullText() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function provideMakeTitleSafe_invalid() {
|
|
|
|
|
yield 'bad namespace' => [ -1234, 'Foo' ];
|
|
|
|
|
yield 'empty' => [ '', NS_MAIN, '' ];
|
|
|
|
|
yield 'bad character' => [ NS_MAIN, 'Foo|Bar' ];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideMakeTitleSafe_invalid
|
|
|
|
|
* @covers Title::makeTitleSafe
|
|
|
|
|
*/
|
|
|
|
|
public function testMakeTitleSafe_invalid( $ns, $text, $fragment = '', $interwiki = '' ) {
|
|
|
|
|
$this->installFakeInterwikiLookup();
|
|
|
|
|
$title = Title::makeTitleSafe( $ns, $text, $fragment, $interwiki );
|
|
|
|
|
|
|
|
|
|
$this->assertNull( $title );
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-22 13:34:55 +00:00
|
|
|
}
|