2010-12-14 16:26:35 +00:00
|
|
|
<?php
|
|
|
|
|
|
2012-09-05 16:54:15 +00:00
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @group Database
|
|
|
|
|
* ^--- needed for language cache stuff
|
|
|
|
|
*/
|
2010-12-28 18:17:16 +00:00
|
|
|
class TitleTest extends MediaWikiTestCase {
|
2012-10-08 10:56:20 +00:00
|
|
|
protected function setUp() {
|
|
|
|
|
parent::setUp();
|
|
|
|
|
|
|
|
|
|
$this->setMwGlobals( array(
|
|
|
|
|
'wgLanguageCode' => 'en',
|
|
|
|
|
'wgContLang' => Language::factory( 'en' ),
|
|
|
|
|
// User language
|
|
|
|
|
'wgLang' => Language::factory( 'en' ),
|
|
|
|
|
'wgAllowUserJs' => false,
|
|
|
|
|
'wgDefaultLanguageVariant' => false,
|
|
|
|
|
) );
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-14 16:26:35 +00:00
|
|
|
function testLegalChars() {
|
|
|
|
|
$titlechars = Title::legalChars();
|
|
|
|
|
|
|
|
|
|
foreach ( range( 1, 255 ) as $num ) {
|
|
|
|
|
$chr = chr( $num );
|
|
|
|
|
if ( strpos( "#[]{}<>|", $chr ) !== false || preg_match( "/[\\x00-\\x1f\\x7f]/", $chr ) ) {
|
|
|
|
|
$this->assertFalse( (bool)preg_match( "/[$titlechars]/", $chr ), "chr($num) = $chr is not a valid titlechar" );
|
|
|
|
|
} else {
|
|
|
|
|
$this->assertTrue( (bool)preg_match( "/[$titlechars]/", $chr ), "chr($num) = $chr is a valid titlechar" );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-05-13 11:41:17 +00:00
|
|
|
|
2011-09-22 21:35:24 +00:00
|
|
|
/**
|
2012-10-08 10:56:20 +00:00
|
|
|
* @dataProvider provideBug31100
|
2011-09-22 21:35:24 +00:00
|
|
|
*/
|
|
|
|
|
function testBug31100FixSpecialName( $text, $expectedParam ) {
|
|
|
|
|
$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;
|
|
|
|
|
}
|
|
|
|
|
$this->assertEquals( $expectedParam, $par, "Bug 31100 regression check: Title->fixSpecialName() should preserve parameter" );
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-08 10:56:20 +00:00
|
|
|
public static function provideBug31100() {
|
2011-09-22 21:35:24 +00:00
|
|
|
return array(
|
|
|
|
|
array( 'Special:Version', null ),
|
|
|
|
|
array( 'Special:Version/', '' ),
|
|
|
|
|
array( 'Special:Version/param', 'param' ),
|
|
|
|
|
);
|
|
|
|
|
}
|
2013-02-14 11:36:35 +00:00
|
|
|
|
2011-09-29 18:35:34 +00:00
|
|
|
/**
|
|
|
|
|
* Auth-less test of Title::isValidMoveOperation
|
2013-02-14 11:36:35 +00:00
|
|
|
*
|
2011-10-02 21:07:17 +00:00
|
|
|
* @group Database
|
2011-09-29 18:35:34 +00:00
|
|
|
* @param string $source
|
|
|
|
|
* @param string $target
|
2012-02-01 20:53:38 +00:00
|
|
|
* @param array|string|true $expected Required error
|
2012-10-08 10:56:20 +00:00
|
|
|
* @dataProvider provideTestIsValidMoveOperation
|
2011-09-29 18:35:34 +00:00
|
|
|
*/
|
|
|
|
|
function testIsValidMoveOperation( $source, $target, $expected ) {
|
|
|
|
|
$title = Title::newFromText( $source );
|
|
|
|
|
$nt = Title::newFromText( $target );
|
|
|
|
|
$errors = $title->isValidMoveOperation( $nt, false );
|
|
|
|
|
if ( $expected === true ) {
|
|
|
|
|
$this->assertTrue( $errors );
|
|
|
|
|
} else {
|
|
|
|
|
$errors = $this->flattenErrorsArray( $errors );
|
|
|
|
|
foreach ( (array)$expected as $error ) {
|
|
|
|
|
$this->assertContains( $error, $errors );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-02-14 11:36:35 +00:00
|
|
|
|
2012-08-07 22:06:12 +00:00
|
|
|
/**
|
|
|
|
|
* Provides test parameter values for testIsValidMoveOperation()
|
|
|
|
|
*/
|
|
|
|
|
function dataTestIsValidMoveOperation() {
|
|
|
|
|
return array(
|
|
|
|
|
array( 'Test', 'Test', 'selfmove' ),
|
|
|
|
|
array( 'File:Test.jpg', 'Page', 'imagenocrossnamespace' )
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Auth-less test of Title::userCan
|
|
|
|
|
*
|
|
|
|
|
* @param array $whitelistRegexp
|
|
|
|
|
* @param string $source
|
|
|
|
|
* @param string $action
|
|
|
|
|
* @param array|string|true $expected Required error
|
|
|
|
|
*
|
2013-03-14 03:56:42 +00:00
|
|
|
* @covers Title::checkReadPermissions
|
2012-08-07 22:06:12 +00:00
|
|
|
* @dataProvider dataWgWhitelistReadRegexp
|
|
|
|
|
*/
|
2013-02-14 11:36:35 +00:00
|
|
|
function testWgWhitelistReadRegexp( $whitelistRegexp, $source, $action, $expected ) {
|
2012-08-07 22:06:12 +00:00
|
|
|
// $wgWhitelistReadRegexp must be an array. Since the provided test cases
|
|
|
|
|
// usually have only one regex, it is more concise to write the lonely regex
|
|
|
|
|
// as a string. Thus we cast to an array() to honor $wgWhitelistReadRegexp
|
|
|
|
|
// type requisite.
|
2013-02-14 11:36:35 +00:00
|
|
|
if ( is_string( $whitelistRegexp ) ) {
|
2012-08-07 22:06:12 +00:00
|
|
|
$whitelistRegexp = array( $whitelistRegexp );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$title = Title::newFromDBkey( $source );
|
|
|
|
|
|
|
|
|
|
global $wgGroupPermissions;
|
|
|
|
|
$oldPermissions = $wgGroupPermissions;
|
|
|
|
|
// Disallow all so we can ensure our regex works
|
|
|
|
|
$wgGroupPermissions = array();
|
|
|
|
|
$wgGroupPermissions['*']['read'] = false;
|
|
|
|
|
|
|
|
|
|
global $wgWhitelistRead;
|
|
|
|
|
$oldWhitelist = $wgWhitelistRead;
|
|
|
|
|
// Undo any LocalSettings explicite whitelists so they won't cause a
|
|
|
|
|
// failing test to succeed. Set it to some random non sense just
|
|
|
|
|
// to make sure we properly test Title::checkReadPermissions()
|
|
|
|
|
$wgWhitelistRead = array( 'some random non sense title' );
|
|
|
|
|
|
|
|
|
|
global $wgWhitelistReadRegexp;
|
2013-02-14 11:36:35 +00:00
|
|
|
$oldWhitelistRegexp = $wgWhitelistReadRegexp;
|
|
|
|
|
$wgWhitelistReadRegexp = $whitelistRegexp;
|
2012-08-07 22:06:12 +00:00
|
|
|
|
|
|
|
|
// Just use $wgUser which in test is a user object for '127.0.0.1'
|
|
|
|
|
global $wgUser;
|
|
|
|
|
// Invalidate user rights cache to take in account $wgGroupPermissions
|
|
|
|
|
// change above.
|
|
|
|
|
$wgUser->clearInstanceCache();
|
|
|
|
|
$errors = $title->userCan( $action, $wgUser );
|
|
|
|
|
|
|
|
|
|
// Restore globals
|
|
|
|
|
$wgGroupPermissions = $oldPermissions;
|
|
|
|
|
$wgWhitelistRead = $oldWhitelist;
|
|
|
|
|
$wgWhitelistReadRegexp = $oldWhitelistRegexp;
|
|
|
|
|
|
2013-02-14 11:36:35 +00:00
|
|
|
if ( is_bool( $expected ) ) {
|
2012-08-07 22:06:12 +00:00
|
|
|
# Forge the assertion message depending on the assertion expectation
|
|
|
|
|
$allowableness = $expected
|
|
|
|
|
? " should be allowed"
|
2013-02-14 11:36:35 +00:00
|
|
|
: " should NOT be allowed";
|
2012-08-07 22:06:12 +00:00
|
|
|
$this->assertEquals( $expected, $errors, "User action '$action' on [[$source]] $allowableness." );
|
|
|
|
|
} else {
|
|
|
|
|
$errors = $this->flattenErrorsArray( $errors );
|
|
|
|
|
foreach ( (array)$expected as $error ) {
|
|
|
|
|
$this->assertContains( $error, $errors );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Provides test parameter values for testWgWhitelistReadRegexp()
|
|
|
|
|
*/
|
|
|
|
|
function dataWgWhitelistReadRegexp() {
|
2013-02-14 11:36:35 +00:00
|
|
|
$ALLOWED = true;
|
2012-08-07 22:06:12 +00:00
|
|
|
$DISALLOWED = false;
|
|
|
|
|
|
|
|
|
|
return array(
|
|
|
|
|
// Everything, if this doesn't work, we're really in trouble
|
|
|
|
|
array( '/.*/', 'Main_Page', 'read', $ALLOWED ),
|
|
|
|
|
array( '/.*/', 'Main_Page', 'edit', $DISALLOWED ),
|
|
|
|
|
|
|
|
|
|
// We validate against the title name, not the db key
|
|
|
|
|
array( '/^Main_Page$/', 'Main_Page', 'read', $DISALLOWED ),
|
|
|
|
|
// Main page
|
|
|
|
|
array( '/^Main/', 'Main_Page', 'read', $ALLOWED ),
|
|
|
|
|
array( '/^Main.*/', 'Main_Page', 'read', $ALLOWED ),
|
|
|
|
|
// With spaces
|
|
|
|
|
array( '/Mic\sCheck/', 'Mic Check', 'read', $ALLOWED ),
|
|
|
|
|
// Unicode multibyte
|
|
|
|
|
// ...without unicode modifier
|
|
|
|
|
array( '/Unicode Test . Yes/', 'Unicode Test Ñ Yes', 'read', $DISALLOWED ),
|
|
|
|
|
// ...with unicode modifier
|
|
|
|
|
array( '/Unicode Test . Yes/u', 'Unicode Test Ñ Yes', 'read', $ALLOWED ),
|
|
|
|
|
// Case insensitive
|
|
|
|
|
array( '/MiC ChEcK/', 'mic check', 'read', $DISALLOWED ),
|
|
|
|
|
array( '/MiC ChEcK/i', 'mic check', 'read', $ALLOWED ),
|
|
|
|
|
|
|
|
|
|
// From DefaultSettings.php:
|
|
|
|
|
array( "@^UsEr.*@i", 'User is banned', 'read', $ALLOWED ),
|
|
|
|
|
array( "@^UsEr.*@i", 'User:John Doe', 'read', $ALLOWED ),
|
|
|
|
|
|
|
|
|
|
// With namespaces:
|
|
|
|
|
array( '/^Special:NewPages$/', 'Special:NewPages', 'read', $ALLOWED ),
|
|
|
|
|
array( null, 'Special:Newpages', 'read', $DISALLOWED ),
|
|
|
|
|
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-29 18:35:34 +00:00
|
|
|
function flattenErrorsArray( $errors ) {
|
|
|
|
|
$result = array();
|
|
|
|
|
foreach ( $errors as $error ) {
|
|
|
|
|
$result[] = $error[0];
|
|
|
|
|
}
|
|
|
|
|
return $result;
|
|
|
|
|
}
|
2013-02-14 11:36:35 +00:00
|
|
|
|
2012-10-08 10:56:20 +00:00
|
|
|
public static function provideTestIsValidMoveOperation() {
|
2013-02-14 11:36:35 +00:00
|
|
|
return array(
|
2011-09-29 18:35:34 +00:00
|
|
|
array( 'Test', 'Test', 'selfmove' ),
|
|
|
|
|
array( 'File:Test.jpg', 'Page', 'imagenocrossnamespace' )
|
|
|
|
|
);
|
|
|
|
|
}
|
2012-08-30 20:04:42 +00:00
|
|
|
|
2012-06-02 18:07:46 +00:00
|
|
|
/**
|
|
|
|
|
* @dataProvider provideCasesForGetpageviewlanguage
|
|
|
|
|
*/
|
2012-10-08 10:56:20 +00:00
|
|
|
function testGetpageviewlanguage( $expected, $titleText, $contLang, $lang, $variant, $msg = '' ) {
|
|
|
|
|
global $wgLanguageCode, $wgContLang, $wgLang, $wgDefaultLanguageVariant, $wgAllowUserJs;
|
|
|
|
|
|
|
|
|
|
// Setup environnement for this test
|
2012-06-02 18:07:46 +00:00
|
|
|
$wgLanguageCode = $contLang;
|
2012-10-08 10:56:20 +00:00
|
|
|
$wgContLang = Language::factory( $contLang );
|
|
|
|
|
$wgLang = Language::factory( $lang );
|
2012-06-02 18:07:46 +00:00
|
|
|
$wgDefaultLanguageVariant = $variant;
|
2012-10-08 10:56:20 +00:00
|
|
|
$wgAllowUserJs = true;
|
2012-06-02 18:07:46 +00:00
|
|
|
|
|
|
|
|
$title = Title::newFromText( $titleText );
|
|
|
|
|
$this->assertInstanceOf( 'Title', $title,
|
|
|
|
|
"Test must be passed a valid title text, you gave '$titleText'"
|
|
|
|
|
);
|
|
|
|
|
$this->assertEquals( $expected,
|
|
|
|
|
$title->getPageViewLanguage()->getCode(),
|
|
|
|
|
$msg
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-22 02:12:37 +00:00
|
|
|
public static function provideCasesForGetpageviewlanguage() {
|
2012-06-02 18:07:46 +00:00
|
|
|
# Format:
|
|
|
|
|
# - expected
|
|
|
|
|
# - Title name
|
|
|
|
|
# - wgContLang (expected in most case)
|
|
|
|
|
# - wgLang (on some specific pages)
|
|
|
|
|
# - wgDefaultLanguageVariant
|
|
|
|
|
# - Optional message
|
|
|
|
|
return array(
|
2012-10-15 12:50:21 +00:00
|
|
|
array( 'fr', 'Help:I_need_somebody', 'fr', 'fr', false ),
|
|
|
|
|
array( 'es', 'Help:I_need_somebody', 'es', 'zh-tw', false ),
|
|
|
|
|
array( 'zh', 'Help:I_need_somebody', 'zh', 'zh-tw', false ),
|
2012-06-02 18:07:46 +00:00
|
|
|
|
2013-02-14 11:36:35 +00:00
|
|
|
array( 'es', 'Help:I_need_somebody', 'es', 'zh-tw', 'zh-cn' ),
|
|
|
|
|
array( 'es', 'MediaWiki:About', 'es', 'zh-tw', 'zh-cn' ),
|
|
|
|
|
array( 'es', 'MediaWiki:About/', 'es', 'zh-tw', 'zh-cn' ),
|
|
|
|
|
array( 'de', 'MediaWiki:About/de', 'es', 'zh-tw', 'zh-cn' ),
|
|
|
|
|
array( 'en', 'MediaWiki:Common.js', 'es', 'zh-tw', 'zh-cn' ),
|
|
|
|
|
array( 'en', 'MediaWiki:Common.css', 'es', 'zh-tw', 'zh-cn' ),
|
|
|
|
|
array( 'en', 'User:JohnDoe/Common.js', 'es', 'zh-tw', 'zh-cn' ),
|
|
|
|
|
array( 'en', 'User:JohnDoe/Monobook.css', 'es', 'zh-tw', 'zh-cn' ),
|
|
|
|
|
|
|
|
|
|
array( 'zh-cn', 'Help:I_need_somebody', 'zh', 'zh-tw', 'zh-cn' ),
|
|
|
|
|
array( 'zh', 'MediaWiki:About', 'zh', 'zh-tw', 'zh-cn' ),
|
|
|
|
|
array( 'zh', 'MediaWiki:About/', 'zh', 'zh-tw', 'zh-cn' ),
|
|
|
|
|
array( 'de', 'MediaWiki:About/de', 'zh', 'zh-tw', 'zh-cn' ),
|
|
|
|
|
array( 'zh-cn', 'MediaWiki:About/zh-cn', 'zh', 'zh-tw', 'zh-cn' ),
|
|
|
|
|
array( 'zh-tw', 'MediaWiki:About/zh-tw', 'zh', 'zh-tw', 'zh-cn' ),
|
|
|
|
|
array( 'en', 'MediaWiki:Common.js', 'zh', 'zh-tw', 'zh-cn' ),
|
|
|
|
|
array( 'en', 'MediaWiki:Common.css', 'zh', 'zh-tw', 'zh-cn' ),
|
|
|
|
|
array( 'en', 'User:JohnDoe/Common.js', 'zh', 'zh-tw', 'zh-cn' ),
|
|
|
|
|
array( 'en', 'User:JohnDoe/Monobook.css', 'zh', 'zh-tw', 'zh-cn' ),
|
|
|
|
|
|
|
|
|
|
array( 'zh-tw', 'Special:NewPages', 'es', 'zh-tw', 'zh-cn' ),
|
|
|
|
|
array( '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
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideBaseTitleCases
|
|
|
|
|
*/
|
2013-02-14 11:36:35 +00:00
|
|
|
function testExtractingBaseTextFromTitle( $title, $expected, $msg = '' ) {
|
2012-08-30 20:04:42 +00:00
|
|
|
$title = Title::newFromText( $title );
|
|
|
|
|
$this->assertEquals( $expected,
|
|
|
|
|
$title->getBaseText(),
|
|
|
|
|
$msg
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-22 02:12:37 +00:00
|
|
|
public static function provideBaseTitleCases() {
|
2012-08-30 20:04:42 +00:00
|
|
|
return array(
|
|
|
|
|
# Title, expected base, optional message
|
2013-02-14 11:36:35 +00:00
|
|
|
array( 'User:John_Doe/subOne/subTwo', 'John Doe/subOne' ),
|
|
|
|
|
array( 'User:Foo/Bar/Baz', 'Foo/Bar' ),
|
2012-08-30 20:04:42 +00:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideRootTitleCases
|
|
|
|
|
*/
|
2013-02-14 11:36:35 +00:00
|
|
|
function testExtractingRootTextFromTitle( $title, $expected, $msg = '' ) {
|
2012-08-30 20:04:42 +00:00
|
|
|
$title = Title::newFromText( $title );
|
|
|
|
|
$this->assertEquals( $expected,
|
|
|
|
|
$title->getRootText(),
|
|
|
|
|
$msg
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-08 10:56:20 +00:00
|
|
|
public static function provideRootTitleCases() {
|
2012-08-30 20:04:42 +00:00
|
|
|
return array(
|
|
|
|
|
# Title, expected base, optional message
|
2013-02-14 11:36:35 +00:00
|
|
|
array( 'User:John_Doe/subOne/subTwo', 'John Doe' ),
|
|
|
|
|
array( 'User:Foo/Bar/Baz', 'Foo' ),
|
2012-08-30 20:04:42 +00:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @todo Handle $wgNamespacesWithSubpages cases
|
|
|
|
|
* @dataProvider provideSubpageTitleCases
|
|
|
|
|
*/
|
2013-02-14 11:36:35 +00:00
|
|
|
function testExtractingSubpageTextFromTitle( $title, $expected, $msg = '' ) {
|
2012-08-30 20:04:42 +00:00
|
|
|
$title = Title::newFromText( $title );
|
|
|
|
|
$this->assertEquals( $expected,
|
|
|
|
|
$title->getSubpageText(),
|
|
|
|
|
$msg
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-22 02:12:37 +00:00
|
|
|
public static function provideSubpageTitleCases() {
|
2012-08-30 20:04:42 +00:00
|
|
|
return array(
|
|
|
|
|
# Title, expected base, optional message
|
2013-02-14 11:36:35 +00:00
|
|
|
array( 'User:John_Doe/subOne/subTwo', 'subTwo' ),
|
|
|
|
|
array( 'User:John_Doe/subOne', 'subOne' ),
|
2012-08-30 20:04:42 +00:00
|
|
|
);
|
|
|
|
|
}
|
2010-12-14 16:26:35 +00:00
|
|
|
}
|