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,
|
|
|
|
|
) );
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-21 21:09:13 +00:00
|
|
|
/**
|
|
|
|
|
* @covers Title::legalChars
|
|
|
|
|
*/
|
|
|
|
|
public function testLegalChars() {
|
2010-12-14 16:26:35 +00:00
|
|
|
$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
|
|
|
|
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
|
|
|
/**
|
|
|
|
|
* See also mediawiki.Title.test.js
|
2013-10-21 21:09:13 +00:00
|
|
|
* @covers Title::secureAndSplit
|
|
|
|
|
* @todo This method should be split into 2 separate tests each with a provider
|
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
|
|
|
*/
|
2013-10-21 21:09:13 +00:00
|
|
|
public function testSecureAndSplit() {
|
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
|
|
|
// Valid
|
|
|
|
|
foreach ( array(
|
|
|
|
|
'Sandbox',
|
|
|
|
|
'A "B"',
|
|
|
|
|
'A \'B\'',
|
|
|
|
|
'.com',
|
|
|
|
|
'~',
|
|
|
|
|
'"',
|
|
|
|
|
'\'',
|
|
|
|
|
'Talk:Sandbox',
|
|
|
|
|
'Talk:Foo:Sandbox',
|
|
|
|
|
'File:Example.svg',
|
|
|
|
|
'File_talk:Example.svg',
|
|
|
|
|
'Foo/.../Sandbox',
|
|
|
|
|
'Sandbox/...',
|
|
|
|
|
'A~~',
|
|
|
|
|
// Length is 256 total, but only title part matters
|
|
|
|
|
'Category:' . str_repeat( 'x', 248 ),
|
|
|
|
|
str_repeat( 'x', 252 )
|
|
|
|
|
) as $text ) {
|
|
|
|
|
$this->assertInstanceOf( 'Title', Title::newFromText( $text ), "Valid: $text" );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Invalid
|
|
|
|
|
foreach ( array(
|
|
|
|
|
'',
|
2013-12-06 17:12:24 +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
|
|
|
'__ __',
|
|
|
|
|
' __ ',
|
|
|
|
|
// Bad characters forbidden regardless of wgLegalTitleChars
|
|
|
|
|
'A [ B',
|
|
|
|
|
'A ] B',
|
|
|
|
|
'A { B',
|
|
|
|
|
'A } B',
|
|
|
|
|
'A < B',
|
|
|
|
|
'A > B',
|
|
|
|
|
'A | B',
|
|
|
|
|
// URL encoding
|
|
|
|
|
'A%20B',
|
|
|
|
|
'A%23B',
|
|
|
|
|
'A%2523B',
|
|
|
|
|
// 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.
|
|
|
|
|
//'A é B',
|
|
|
|
|
//'A é B',
|
|
|
|
|
//'A é B',
|
|
|
|
|
// Subject of NS_TALK does not roundtrip to NS_MAIN
|
|
|
|
|
'Talk:File:Example.svg',
|
|
|
|
|
// Directory navigation
|
|
|
|
|
'.',
|
|
|
|
|
'..',
|
|
|
|
|
'./Sandbox',
|
|
|
|
|
'../Sandbox',
|
|
|
|
|
'Foo/./Sandbox',
|
|
|
|
|
'Foo/../Sandbox',
|
|
|
|
|
'Sandbox/.',
|
|
|
|
|
'Sandbox/..',
|
|
|
|
|
// Tilde
|
|
|
|
|
'A ~~~ Name',
|
|
|
|
|
'A ~~~~ Signature',
|
|
|
|
|
'A ~~~~~ Timestamp',
|
|
|
|
|
str_repeat( 'x', 256 ),
|
|
|
|
|
// Namespace prefix without actual title
|
|
|
|
|
'Talk:',
|
|
|
|
|
'Category: ',
|
|
|
|
|
'Category: #bar'
|
|
|
|
|
) as $text ) {
|
|
|
|
|
$this->assertNull( Title::newFromText( $text ), "Invalid: $text" );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-30 21:00:40 +00:00
|
|
|
public static function provideConvertByteClassToUnicodeClass() {
|
|
|
|
|
return array(
|
|
|
|
|
array(
|
|
|
|
|
' %!"$&\'()*,\\-.\\/0-9:;=?@A-Z\\\\^_`a-z~\\x80-\\xFF+',
|
|
|
|
|
' %!"$&\'()*,\\-./0-9:;=?@A-Z\\\\\\^_`a-z~+\\u0080-\\uFFFF',
|
|
|
|
|
),
|
|
|
|
|
array(
|
|
|
|
|
'QWERTYf-\\xFF+',
|
|
|
|
|
'QWERTYf-\\x7F+\\u0080-\\uFFFF',
|
|
|
|
|
),
|
|
|
|
|
array(
|
|
|
|
|
'QWERTY\\x66-\\xFD+',
|
|
|
|
|
'QWERTYf-\\x7F+\\u0080-\\uFFFF',
|
|
|
|
|
),
|
|
|
|
|
array(
|
|
|
|
|
'QWERTYf-y+',
|
|
|
|
|
'QWERTYf-y+',
|
|
|
|
|
),
|
|
|
|
|
array(
|
|
|
|
|
'QWERTYf-\\x80+',
|
|
|
|
|
'QWERTYf-\\x7F+\\u0080-\\uFFFF',
|
|
|
|
|
),
|
|
|
|
|
array(
|
|
|
|
|
'QWERTY\\x66-\\x80+\\x23',
|
|
|
|
|
'QWERTYf-\\x7F+#\\u0080-\\uFFFF',
|
|
|
|
|
),
|
|
|
|
|
array(
|
|
|
|
|
'QWERTY\\x66-\\x80+\\xD3',
|
|
|
|
|
'QWERTYf-\\x7F+\\u0080-\\uFFFF',
|
|
|
|
|
),
|
|
|
|
|
array(
|
|
|
|
|
'\\\\\\x99',
|
|
|
|
|
'\\\\\\u0080-\\uFFFF',
|
|
|
|
|
),
|
|
|
|
|
array(
|
|
|
|
|
'-\\x99',
|
|
|
|
|
'\\-\\u0080-\\uFFFF',
|
|
|
|
|
),
|
|
|
|
|
array(
|
|
|
|
|
'QWERTY\\-\\x99',
|
|
|
|
|
'QWERTY\\-\\u0080-\\uFFFF',
|
|
|
|
|
),
|
|
|
|
|
array(
|
|
|
|
|
'\\\\x99',
|
|
|
|
|
'\\\\x99',
|
|
|
|
|
),
|
|
|
|
|
array(
|
|
|
|
|
'A-\\x9F',
|
|
|
|
|
'A-\\x7F\\u0080-\\uFFFF',
|
|
|
|
|
),
|
|
|
|
|
array(
|
|
|
|
|
'\\x66-\\x77QWERTY\\x88-\\x91FXZ',
|
|
|
|
|
'f-wQWERTYFXZ\\u0080-\\uFFFF',
|
|
|
|
|
),
|
|
|
|
|
array(
|
|
|
|
|
'\\x66-\\x99QWERTY\\xAA-\\xEEFXZ',
|
|
|
|
|
'f-\\x7FQWERTYFXZ\\u0080-\\uFFFF',
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideConvertByteClassToUnicodeClass
|
2013-10-21 21:09:13 +00:00
|
|
|
* @covers Title::convertByteClassToUnicodeClass
|
2013-08-30 21:00:40 +00:00
|
|
|
*/
|
2013-10-21 21:09:13 +00:00
|
|
|
public function testConvertByteClassToUnicodeClass( $byteClass, $unicodeClass ) {
|
2013-08-30 21:00:40 +00:00
|
|
|
$this->assertEquals( $unicodeClass, Title::convertByteClassToUnicodeClass( $byteClass ) );
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-22 21:35:24 +00:00
|
|
|
/**
|
2012-10-08 10:56:20 +00:00
|
|
|
* @dataProvider provideBug31100
|
2013-10-21 21:09:13 +00:00
|
|
|
* @covers Title::fixSpecialName
|
2011-09-22 21:35:24 +00:00
|
|
|
*/
|
2013-10-21 21:09:13 +00:00
|
|
|
public function testBug31100FixSpecialName( $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;
|
|
|
|
|
}
|
|
|
|
|
$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
|
2013-10-21 21:09:13 +00:00
|
|
|
* @param array|string|bool $expected Required error
|
2012-10-08 10:56:20 +00:00
|
|
|
* @dataProvider provideTestIsValidMoveOperation
|
2013-10-21 21:09:13 +00:00
|
|
|
* @covers Title::isValidMoveOperation
|
2011-09-29 18:35:34 +00:00
|
|
|
*/
|
2013-10-21 21:09:13 +00:00
|
|
|
public function testIsValidMoveOperation( $source, $target, $expected ) {
|
2011-09-29 18:35:34 +00:00
|
|
|
$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()
|
|
|
|
|
*/
|
2013-10-21 21:09:13 +00:00
|
|
|
public function dataTestIsValidMoveOperation() {
|
2012-08-07 22:06:12 +00:00
|
|
|
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
|
2013-10-21 21:09:13 +00:00
|
|
|
* @param array|string|bool $expected Required error
|
2012-08-07 22:06:12 +00:00
|
|
|
*
|
2013-03-14 03:56:42 +00:00
|
|
|
* @covers Title::checkReadPermissions
|
2012-08-07 22:06:12 +00:00
|
|
|
* @dataProvider dataWgWhitelistReadRegexp
|
|
|
|
|
*/
|
2013-10-21 21:09:13 +00:00
|
|
|
public 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()
|
|
|
|
|
*/
|
2013-10-21 21:09:13 +00:00
|
|
|
public 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 ),
|
|
|
|
|
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-21 21:09:13 +00:00
|
|
|
public function flattenErrorsArray( $errors ) {
|
2011-09-29 18:35:34 +00:00
|
|
|
$result = array();
|
|
|
|
|
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
|
|
|
|
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
|
|
|
/**
|
2013-10-21 21:09:13 +00:00
|
|
|
* @dataProvider provideGetPageViewLanguage
|
|
|
|
|
* @covers Title::getPageViewLanguage
|
2012-06-02 18:07:46 +00:00
|
|
|
*/
|
2013-10-21 21:09:13 +00:00
|
|
|
public function testGetPageViewLanguage( $expected, $titleText, $contLang, $lang, $variant, $msg = '' ) {
|
2012-10-08 10:56:20 +00:00
|
|
|
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-10-21 21:09:13 +00:00
|
|
|
public static function provideGetPageViewLanguage() {
|
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-10-21 21:09:13 +00:00
|
|
|
* @covers Title::getBaseText
|
2012-08-30 20:04:42 +00:00
|
|
|
*/
|
2013-10-21 21:09:13 +00:00
|
|
|
public function testGetBaseText( $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-10-21 21:09:13 +00:00
|
|
|
* @covers Title::getRootText
|
2012-08-30 20:04:42 +00:00
|
|
|
*/
|
2013-10-21 21:09:13 +00:00
|
|
|
public function testGetRootText( $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-10-21 21:09:13 +00:00
|
|
|
* @covers Title::getSubpageText
|
2012-08-30 20:04:42 +00:00
|
|
|
*/
|
2013-10-21 21:09:13 +00:00
|
|
|
public function testGetSubpageText( $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
|
|
|
}
|