2010-12-14 16:26:35 +00:00
|
|
|
<?php
|
|
|
|
|
|
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
|
|
|
*/
|
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();
|
|
|
|
|
|
2016-02-17 09:09:32 +00:00
|
|
|
$this->setMwGlobals( [
|
2012-10-08 10:56:20 +00:00
|
|
|
'wgAllowUserJs' => false,
|
|
|
|
|
'wgDefaultLanguageVariant' => false,
|
2014-11-13 18:15:40 +00:00
|
|
|
'wgMetaNamespace' => 'Project',
|
2016-02-17 09:09:32 +00:00
|
|
|
] );
|
2016-03-09 16:47:58 +00:00
|
|
|
$this->setUserLang( 'en' );
|
|
|
|
|
$this->setContentLang( 'en' );
|
2012-10-08 10:56:20 +00:00
|
|
|
}
|
|
|
|
|
|
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 ) ) {
|
2014-04-24 12:50:36 +00:00
|
|
|
$this->assertFalse(
|
|
|
|
|
(bool)preg_match( "/[$titlechars]/", $chr ),
|
|
|
|
|
"chr($num) = $chr is not a valid titlechar"
|
|
|
|
|
);
|
2010-12-14 16:26:35 +00:00
|
|
|
} else {
|
2014-04-24 12:50:36 +00:00
|
|
|
$this->assertTrue(
|
|
|
|
|
(bool)preg_match( "/[$titlechars]/", $chr ),
|
|
|
|
|
"chr($num) = $chr is a valid titlechar"
|
|
|
|
|
);
|
2010-12-14 16:26:35 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-05-13 11:41:17 +00:00
|
|
|
|
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',
|
|
|
|
|
// 'A é B',
|
|
|
|
|
// '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
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function secureAndSplitGlobals() {
|
2016-02-17 09:09:32 +00:00
|
|
|
$this->setMwGlobals( [
|
|
|
|
|
'wgLocalInterwikis' => [ 'localtestiw' ],
|
|
|
|
|
'wgHooks' => [
|
|
|
|
|
'InterwikiLoadPrefix' => [
|
2014-09-05 17:52:31 +00:00
|
|
|
function ( $prefix, &$data ) {
|
|
|
|
|
if ( $prefix === 'localtestiw' ) {
|
2016-02-17 09:09:32 +00:00
|
|
|
$data = [ 'iw_url' => 'localtestiw' ];
|
2014-09-05 17:52:31 +00:00
|
|
|
} elseif ( $prefix === 'remotetestiw' ) {
|
2016-02-17 09:09:32 +00:00
|
|
|
$data = [ 'iw_url' => 'remotetestiw' ];
|
2014-09-05 17:52:31 +00:00
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2016-02-17 09:09:32 +00:00
|
|
|
]
|
|
|
|
|
]
|
|
|
|
|
] );
|
2016-04-25 05:41:32 +00:00
|
|
|
|
|
|
|
|
// Reset TitleParser since we modified $wgLocalInterwikis
|
|
|
|
|
$this->setService( 'TitleParser', new MediaWikiTitleCodec(
|
|
|
|
|
Language::factory( 'en' ),
|
|
|
|
|
new GenderCache(),
|
|
|
|
|
[ 'localtestiw' ]
|
|
|
|
|
) );
|
2014-09-05 17:52:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* See also mediawiki.Title.test.js
|
|
|
|
|
* @covers Title::secureAndSplit
|
|
|
|
|
* @dataProvider provideValidSecureAndSplit
|
|
|
|
|
* @note This mainly tests MediaWikiTitleCodec::parseTitle().
|
|
|
|
|
*/
|
|
|
|
|
public function testSecureAndSplitValid( $text ) {
|
|
|
|
|
$this->secureAndSplitGlobals();
|
|
|
|
|
$this->assertInstanceOf( 'Title', Title::newFromText( $text ), "Valid: $text" );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* See also mediawiki.Title.test.js
|
|
|
|
|
* @covers Title::secureAndSplit
|
|
|
|
|
* @dataProvider provideInvalidSecureAndSplit
|
|
|
|
|
* @note This mainly tests MediaWikiTitleCodec::parseTitle().
|
|
|
|
|
*/
|
2015-04-25 22:43:37 +00:00
|
|
|
public function testSecureAndSplitInvalid( $text, $expectedErrorMessage ) {
|
2014-09-05 17:52:31 +00:00
|
|
|
$this->secureAndSplitGlobals();
|
2015-04-25 22:43:37 +00:00
|
|
|
try {
|
|
|
|
|
Title::newFromTextThrow( $text ); // should throw
|
|
|
|
|
$this->assertTrue( false, "Invalid: $text" );
|
|
|
|
|
} 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
|
|
|
}
|
|
|
|
|
|
2013-08-30 21:00:40 +00:00
|
|
|
public static function provideConvertByteClassToUnicodeClass() {
|
2016-02-17 09:09:32 +00:00
|
|
|
return [
|
|
|
|
|
[
|
2013-08-30 21:00:40 +00:00
|
|
|
' %!"$&\'()*,\\-.\\/0-9:;=?@A-Z\\\\^_`a-z~\\x80-\\xFF+',
|
|
|
|
|
' %!"$&\'()*,\\-./0-9:;=?@A-Z\\\\\\^_`a-z~+\\u0080-\\uFFFF',
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[
|
2013-08-30 21:00:40 +00:00
|
|
|
'QWERTYf-\\xFF+',
|
|
|
|
|
'QWERTYf-\\x7F+\\u0080-\\uFFFF',
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[
|
2013-08-30 21:00:40 +00:00
|
|
|
'QWERTY\\x66-\\xFD+',
|
|
|
|
|
'QWERTYf-\\x7F+\\u0080-\\uFFFF',
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[
|
2013-08-30 21:00:40 +00:00
|
|
|
'QWERTYf-y+',
|
|
|
|
|
'QWERTYf-y+',
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[
|
2013-08-30 21:00:40 +00:00
|
|
|
'QWERTYf-\\x80+',
|
|
|
|
|
'QWERTYf-\\x7F+\\u0080-\\uFFFF',
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[
|
2013-08-30 21:00:40 +00:00
|
|
|
'QWERTY\\x66-\\x80+\\x23',
|
|
|
|
|
'QWERTYf-\\x7F+#\\u0080-\\uFFFF',
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[
|
2013-08-30 21:00:40 +00:00
|
|
|
'QWERTY\\x66-\\x80+\\xD3',
|
|
|
|
|
'QWERTYf-\\x7F+\\u0080-\\uFFFF',
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[
|
2013-08-30 21:00:40 +00:00
|
|
|
'\\\\\\x99',
|
|
|
|
|
'\\\\\\u0080-\\uFFFF',
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[
|
2013-08-30 21:00:40 +00:00
|
|
|
'-\\x99',
|
|
|
|
|
'\\-\\u0080-\\uFFFF',
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[
|
2013-08-30 21:00:40 +00:00
|
|
|
'QWERTY\\-\\x99',
|
|
|
|
|
'QWERTY\\-\\u0080-\\uFFFF',
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[
|
2013-08-30 21:00:40 +00:00
|
|
|
'\\\\x99',
|
|
|
|
|
'\\\\x99',
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[
|
2013-08-30 21:00:40 +00:00
|
|
|
'A-\\x9F',
|
|
|
|
|
'A-\\x7F\\u0080-\\uFFFF',
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[
|
2013-08-30 21:00:40 +00:00
|
|
|
'\\x66-\\x77QWERTY\\x88-\\x91FXZ',
|
|
|
|
|
'f-wQWERTYFXZ\\u0080-\\uFFFF',
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
[
|
2013-08-30 21:00:40 +00:00
|
|
|
'\\x66-\\x99QWERTY\\xAA-\\xEEFXZ',
|
|
|
|
|
'f-\\x7FQWERTYFXZ\\u0080-\\uFFFF',
|
2016-02-17 09:09:32 +00:00
|
|
|
],
|
|
|
|
|
];
|
2013-08-30 21:00:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @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
|
|
|
/**
|
2014-08-28 18:38:18 +00:00
|
|
|
* @dataProvider provideSpecialNamesWithAndWithoutParameter
|
2013-10-21 21:09:13 +00:00
|
|
|
* @covers 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
|
|
|
}
|
|
|
|
|
|
2014-08-28 18:38:18 +00:00
|
|
|
public static function provideSpecialNamesWithAndWithoutParameter() {
|
2016-02-17 09:09:32 +00:00
|
|
|
return [
|
|
|
|
|
[ 'Special:Version', null ],
|
|
|
|
|
[ 'Special:Version/', '' ],
|
|
|
|
|
[ 'Special:Version/param', 'param' ],
|
|
|
|
|
];
|
2011-09-22 21:35:24 +00:00
|
|
|
}
|
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-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
|
2014-09-19 06:10:03 +00:00
|
|
|
* @covers Title::validateFileMoveOperation
|
2011-09-29 18:35:34 +00:00
|
|
|
*/
|
2013-10-21 21:09:13 +00:00
|
|
|
public function testIsValidMoveOperation( $source, $target, $expected ) {
|
2014-09-19 06:10:03 +00:00
|
|
|
$this->setMwGlobals( 'wgContentHandlerUseDB', false );
|
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
|
|
|
|
2014-09-18 01:28:26 +00:00
|
|
|
public static function provideTestIsValidMoveOperation() {
|
2016-02-17 09:09:32 +00:00
|
|
|
return [
|
2014-09-19 06:10:03 +00:00
|
|
|
// for Title::isValidMoveOperation
|
2016-02-17 09:09:32 +00:00
|
|
|
[ 'Some page', '', 'badtitletext' ],
|
|
|
|
|
[ 'Test', 'Test', 'selfmove' ],
|
|
|
|
|
[ 'Special:FooBar', 'Test', 'immobile-source-namespace' ],
|
|
|
|
|
[ 'Test', 'Special:FooBar', 'immobile-target-namespace' ],
|
|
|
|
|
[ 'MediaWiki:Common.js', 'Help:Some wikitext page', 'bad-target-model' ],
|
|
|
|
|
[ 'Page', 'File:Test.jpg', 'nonfile-cannot-move-to-file' ],
|
2014-09-19 06:10:03 +00:00
|
|
|
// for Title::validateFileMoveOperation
|
2016-02-17 09:09:32 +00:00
|
|
|
[ 'File:Test.jpg', 'Page', 'imagenocrossnamespace' ],
|
|
|
|
|
];
|
2012-08-07 22:06:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 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 ) ) {
|
2016-02-17 09:09:32 +00:00
|
|
|
$whitelistRegexp = [ $whitelistRegexp ];
|
2012-08-07 22:06:12 +00:00
|
|
|
}
|
|
|
|
|
|
2016-02-17 09:09:32 +00:00
|
|
|
$this->setMwGlobals( [
|
2015-03-28 05:22:51 +00:00
|
|
|
// So User::isEveryoneAllowed( 'read' ) === false
|
2016-02-17 09:09:32 +00:00
|
|
|
'wgGroupPermissions' => [ '*' => [ 'read' => false ] ],
|
|
|
|
|
'wgWhitelistRead' => [ 'some random non sense title' ],
|
2015-03-28 05:22:51 +00:00
|
|
|
'wgWhitelistReadRegexp' => $whitelistRegexp,
|
2016-02-17 09:09:32 +00:00
|
|
|
] );
|
2012-08-07 22:06:12 +00:00
|
|
|
|
2015-03-28 05:22:51 +00:00
|
|
|
$title = Title::newFromDBkey( $source );
|
2012-08-07 22:06:12 +00:00
|
|
|
|
2015-03-28 05:22:51 +00:00
|
|
|
// New anonymous user with no rights
|
|
|
|
|
$user = new User;
|
2016-02-17 09:09:32 +00:00
|
|
|
$user->mRights = [];
|
2015-03-28 05:22:51 +00:00
|
|
|
$errors = $title->userCan( $action, $user );
|
2012-08-07 22:06:12 +00:00
|
|
|
|
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";
|
2014-04-24 12:50:36 +00:00
|
|
|
$this->assertEquals(
|
|
|
|
|
$expected,
|
|
|
|
|
$errors,
|
|
|
|
|
"User action '$action' on [[$source]] $allowableness."
|
|
|
|
|
);
|
2012-08-07 22:06:12 +00:00
|
|
|
} 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;
|
|
|
|
|
|
2016-02-17 09:09:32 +00:00
|
|
|
return [
|
2012-08-07 22:06:12 +00:00
|
|
|
// Everything, if this doesn't work, we're really in trouble
|
2016-02-17 09:09:32 +00:00
|
|
|
[ '/.*/', 'Main_Page', 'read', $ALLOWED ],
|
|
|
|
|
[ '/.*/', 'Main_Page', 'edit', $DISALLOWED ],
|
2012-08-07 22:06:12 +00:00
|
|
|
|
|
|
|
|
// We validate against the title name, not the db key
|
2016-02-17 09:09:32 +00:00
|
|
|
[ '/^Main_Page$/', 'Main_Page', 'read', $DISALLOWED ],
|
2012-08-07 22:06:12 +00:00
|
|
|
// Main page
|
2016-02-17 09:09:32 +00:00
|
|
|
[ '/^Main/', 'Main_Page', 'read', $ALLOWED ],
|
|
|
|
|
[ '/^Main.*/', 'Main_Page', 'read', $ALLOWED ],
|
2012-08-07 22:06:12 +00:00
|
|
|
// With spaces
|
2016-02-17 09:09:32 +00:00
|
|
|
[ '/Mic\sCheck/', 'Mic Check', 'read', $ALLOWED ],
|
2012-08-07 22:06:12 +00:00
|
|
|
// Unicode multibyte
|
|
|
|
|
// ...without unicode modifier
|
2016-02-17 09:09:32 +00:00
|
|
|
[ '/Unicode Test . Yes/', 'Unicode Test Ñ Yes', 'read', $DISALLOWED ],
|
2012-08-07 22:06:12 +00:00
|
|
|
// ...with unicode modifier
|
2016-02-17 09:09:32 +00:00
|
|
|
[ '/Unicode Test . Yes/u', 'Unicode Test Ñ Yes', 'read', $ALLOWED ],
|
2012-08-07 22:06:12 +00:00
|
|
|
// Case insensitive
|
2016-02-17 09:09:32 +00:00
|
|
|
[ '/MiC ChEcK/', 'mic check', 'read', $DISALLOWED ],
|
|
|
|
|
[ '/MiC ChEcK/i', 'mic check', 'read', $ALLOWED ],
|
2012-08-07 22:06:12 +00:00
|
|
|
|
|
|
|
|
// From DefaultSettings.php:
|
2016-02-17 09:09:32 +00:00
|
|
|
[ "@^UsEr.*@i", 'User is banned', 'read', $ALLOWED ],
|
|
|
|
|
[ "@^UsEr.*@i", 'User:John Doe', 'read', $ALLOWED ],
|
2012-08-07 22:06:12 +00:00
|
|
|
|
|
|
|
|
// With namespaces:
|
2016-02-17 09:09:32 +00:00
|
|
|
[ '/^Special:NewPages$/', 'Special:NewPages', 'read', $ALLOWED ],
|
|
|
|
|
[ null, 'Special:Newpages', 'read', $DISALLOWED ],
|
2012-08-07 22:06:12 +00:00
|
|
|
|
2016-02-17 09:09:32 +00:00
|
|
|
];
|
2012-08-07 22:06:12 +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
|
|
|
|
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
|
|
|
*/
|
2014-04-24 12:50:36 +00:00
|
|
|
public function testGetPageViewLanguage( $expected, $titleText, $contLang,
|
|
|
|
|
$lang, $variant, $msg = ''
|
|
|
|
|
) {
|
2012-10-08 10:56:20 +00:00
|
|
|
// Setup environnement for this test
|
2016-02-17 09:09:32 +00:00
|
|
|
$this->setMwGlobals( [
|
2014-10-16 17:44:39 +00:00
|
|
|
'wgDefaultLanguageVariant' => $variant,
|
|
|
|
|
'wgAllowUserJs' => true,
|
2016-02-17 09:09:32 +00:00
|
|
|
] );
|
2016-03-09 16:47:58 +00:00
|
|
|
$this->setUserLang( $lang );
|
|
|
|
|
$this->setContentLang( $contLang );
|
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
|
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
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @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() {
|
2016-02-17 09:09:32 +00:00
|
|
|
return [
|
2012-08-30 20:04:42 +00:00
|
|
|
# Title, expected base, optional message
|
2016-02-17 09:09:32 +00:00
|
|
|
[ 'User:John_Doe/subOne/subTwo', 'John Doe/subOne' ],
|
|
|
|
|
[ '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() {
|
2016-02-17 09:09:32 +00:00
|
|
|
return [
|
2012-08-30 20:04:42 +00:00
|
|
|
# Title, expected base, optional message
|
2016-02-17 09:09:32 +00:00
|
|
|
[ 'User:John_Doe/subOne/subTwo', 'John Doe' ],
|
|
|
|
|
[ '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() {
|
2016-02-17 09:09:32 +00:00
|
|
|
return [
|
2012-08-30 20:04:42 +00:00
|
|
|
# Title, expected base, optional message
|
2016-02-17 09:09:32 +00:00
|
|
|
[ 'User:John_Doe/subOne/subTwo', 'subTwo' ],
|
|
|
|
|
[ 'User:John_Doe/subOne', 'subOne' ],
|
|
|
|
|
];
|
2012-08-30 20:04:42 +00:00
|
|
|
}
|
2014-04-06 13:18:07 +00:00
|
|
|
|
2014-09-18 01:28:26 +00:00
|
|
|
public static function provideNewFromTitleValue() {
|
2016-02-17 09:09:32 +00:00
|
|
|
return [
|
|
|
|
|
[ new TitleValue( NS_MAIN, 'Foo' ) ],
|
|
|
|
|
[ new TitleValue( NS_MAIN, 'Foo', 'bar' ) ],
|
|
|
|
|
[ new TitleValue( NS_USER, 'Hansi_Maier' ) ],
|
|
|
|
|
];
|
2014-04-06 13:18:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2017-12-25 07:28:03 +00:00
|
|
|
* @covers Title::newFromTitleValue
|
2014-04-06 13:18:07 +00:00
|
|
|
* @dataProvider provideNewFromTitleValue
|
|
|
|
|
*/
|
|
|
|
|
public function testNewFromTitleValue( TitleValue $value ) {
|
|
|
|
|
$title = Title::newFromTitleValue( $value );
|
|
|
|
|
|
|
|
|
|
$dbkey = str_replace( ' ', '_', $value->getText() );
|
|
|
|
|
$this->assertEquals( $dbkey, $title->getDBkey() );
|
|
|
|
|
$this->assertEquals( $value->getNamespace(), $title->getNamespace() );
|
|
|
|
|
$this->assertEquals( $value->getFragment(), $title->getFragment() );
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-18 01:28:26 +00:00
|
|
|
public static function provideGetTitleValue() {
|
2016-02-17 09:09:32 +00:00
|
|
|
return [
|
|
|
|
|
[ 'Foo' ],
|
|
|
|
|
[ 'Foo#bar' ],
|
|
|
|
|
[ 'User:Hansi_Maier' ],
|
|
|
|
|
];
|
2014-04-06 13:18:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2017-12-25 07:28:03 +00:00
|
|
|
* @covers Title::getTitleValue
|
2014-04-06 13:18:07 +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() );
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-18 01:28:26 +00:00
|
|
|
public static function provideGetFragment() {
|
2016-02-17 09:09:32 +00:00
|
|
|
return [
|
|
|
|
|
[ 'Foo', '' ],
|
|
|
|
|
[ 'Foo#bar', 'bar' ],
|
|
|
|
|
[ 'Foo#bär', 'bär' ],
|
2014-04-06 13:18:07 +00:00
|
|
|
|
|
|
|
|
// Inner whitespace is normalized
|
2016-02-17 09:09:32 +00:00
|
|
|
[ 'Foo#bar_bar', 'bar bar' ],
|
|
|
|
|
[ 'Foo#bar bar', 'bar bar' ],
|
|
|
|
|
[ 'Foo#bar bar', 'bar bar' ],
|
2014-04-06 13:18:07 +00:00
|
|
|
|
|
|
|
|
// Leading whitespace is kept, trailing whitespace is trimmed.
|
|
|
|
|
// XXX: Is this really want we want?
|
2016-02-17 09:09:32 +00:00
|
|
|
[ 'Foo#_bar_bar_', ' bar bar' ],
|
|
|
|
|
[ 'Foo# bar bar ', ' bar bar' ],
|
|
|
|
|
];
|
2014-04-06 13:18:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2017-12-25 07:28:03 +00:00
|
|
|
* @covers Title::getFragment
|
2014-04-06 13:18:07 +00:00
|
|
|
* @dataProvider provideGetFragment
|
|
|
|
|
*
|
2014-04-17 18:43:42 +00:00
|
|
|
* @param string $full
|
|
|
|
|
* @param string $fragment
|
2014-04-06 13:18:07 +00:00
|
|
|
*/
|
|
|
|
|
public function testGetFragment( $full, $fragment ) {
|
|
|
|
|
$title = Title::newFromText( $full );
|
|
|
|
|
$this->assertEquals( $fragment, $title->getFragment() );
|
|
|
|
|
}
|
2014-06-19 18:36:56 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers Title::isAlwaysKnown
|
|
|
|
|
* @dataProvider provideIsAlwaysKnown
|
|
|
|
|
* @param string $page
|
|
|
|
|
* @param bool $isKnown
|
|
|
|
|
*/
|
|
|
|
|
public function testIsAlwaysKnown( $page, $isKnown ) {
|
|
|
|
|
$title = Title::newFromText( $page );
|
|
|
|
|
$this->assertEquals( $isKnown, $title->isAlwaysKnown() );
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
/**
|
|
|
|
|
* @covers Title::isValid
|
|
|
|
|
* @dataProvider provideIsValid
|
|
|
|
|
* @param Title $title
|
|
|
|
|
* @param bool $isValid
|
|
|
|
|
*/
|
|
|
|
|
public function testIsValid( Title $title, $isValid ) {
|
|
|
|
|
$this->assertEquals( $isValid, $title->isValid(), $title->getPrefixedText() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 ],
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, 'Test' ), true ],
|
|
|
|
|
[ Title::makeTitle( -33, 'Test' ), false ],
|
|
|
|
|
[ Title::makeTitle( 77663399, 'Test' ), false ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-21 19:54:51 +00:00
|
|
|
/**
|
|
|
|
|
* @covers Title::isAlwaysKnown
|
|
|
|
|
*/
|
|
|
|
|
public function testIsAlwaysKnownOnInterwiki() {
|
|
|
|
|
$title = Title::makeTitle( NS_MAIN, 'Interwiki link', '', 'externalwiki' );
|
|
|
|
|
$this->assertTrue( $title->isAlwaysKnown() );
|
|
|
|
|
}
|
2015-04-30 18:55:23 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers Title::exists
|
|
|
|
|
*/
|
|
|
|
|
public function testExists() {
|
|
|
|
|
$title = Title::makeTitle( NS_PROJECT, 'New page' );
|
|
|
|
|
$linkCache = LinkCache::singleton();
|
|
|
|
|
|
|
|
|
|
$article = new Article( $title );
|
|
|
|
|
$page = $article->getPage();
|
|
|
|
|
$page->doEditContent( new WikitextContent( 'Some [[link]]' ), 'summary' );
|
|
|
|
|
|
|
|
|
|
// Tell Title it doesn't know whether it exists
|
|
|
|
|
$title->mArticleID = -1;
|
|
|
|
|
|
|
|
|
|
// Tell the link cache it doesn't exists when it really does
|
|
|
|
|
$linkCache->clearLink( $title );
|
|
|
|
|
$linkCache->addBadLinkObj( $title );
|
|
|
|
|
|
2015-09-30 08:01:28 +00:00
|
|
|
$this->assertEquals(
|
|
|
|
|
false,
|
|
|
|
|
$title->exists(),
|
|
|
|
|
'exists() should rely on link cache unless GAID_FOR_UPDATE is used'
|
|
|
|
|
);
|
|
|
|
|
$this->assertEquals(
|
|
|
|
|
true,
|
|
|
|
|
$title->exists( Title::GAID_FOR_UPDATE ),
|
|
|
|
|
'exists() should re-query database when GAID_FOR_UPDATE is used'
|
|
|
|
|
);
|
2015-04-30 18:55:23 +00:00
|
|
|
}
|
2016-04-20 08:09:23 +00:00
|
|
|
|
2017-06-09 18:29:18 +00:00
|
|
|
public function provideCanHaveTalkPage() {
|
|
|
|
|
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
|
|
|
|
|
],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideCanHaveTalkPage
|
|
|
|
|
* @covers Title::canHaveTalkPage
|
|
|
|
|
*
|
|
|
|
|
* @param Title $title
|
|
|
|
|
* @param bool $expected
|
|
|
|
|
*/
|
|
|
|
|
public function testCanHaveTalkPage( Title $title, $expected ) {
|
|
|
|
|
$actual = $title->canHaveTalkPage();
|
|
|
|
|
$this->assertSame( $expected, $actual, $title->getPrefixedDBkey() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideCanHaveTalkPage
|
|
|
|
|
* @covers Title::canTalk
|
|
|
|
|
*
|
|
|
|
|
* @param Title $title
|
|
|
|
|
* @param bool $expected
|
|
|
|
|
*/
|
|
|
|
|
public function testCanTalk( Title $title, $expected ) {
|
|
|
|
|
$actual = $title->canTalk();
|
|
|
|
|
$this->assertSame( $expected, $actual, $title->getPrefixedDBkey() );
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-01 17:09:13 +00:00
|
|
|
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' ) ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideGetTalkPage_good
|
|
|
|
|
* @covers Title::getTalkPage
|
|
|
|
|
*/
|
|
|
|
|
public function testGetTalkPage_good( Title $title, Title $expected ) {
|
|
|
|
|
$talk = $title->getTalkPage();
|
|
|
|
|
$this->assertSame(
|
|
|
|
|
$expected->getPrefixedDBKey(),
|
|
|
|
|
$talk->getPrefixedDBKey(),
|
|
|
|
|
$title->getPrefixedDBKey()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideGetTalkPage_good
|
|
|
|
|
* @covers Title::getTalkPageIfDefined
|
|
|
|
|
*/
|
|
|
|
|
public function testGetTalkPageIfDefined_good( Title $title ) {
|
|
|
|
|
$talk = $title->getTalkPageIfDefined();
|
|
|
|
|
$this->assertInstanceOf(
|
|
|
|
|
Title::class,
|
|
|
|
|
$talk,
|
|
|
|
|
$title->getPrefixedDBKey()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static function provideGetTalkPage_bad() {
|
|
|
|
|
return [
|
|
|
|
|
[ Title::makeTitle( NS_SPECIAL, 'Test' ) ],
|
|
|
|
|
[ Title::makeTitle( NS_MEDIA, 'Test' ) ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @dataProvider provideGetTalkPage_bad
|
|
|
|
|
* @covers Title::getTalkPageIfDefined
|
|
|
|
|
*/
|
|
|
|
|
public function testGetTalkPageIfDefined_bad( Title $title ) {
|
|
|
|
|
$talk = $title->getTalkPageIfDefined();
|
|
|
|
|
$this->assertNull(
|
|
|
|
|
$talk,
|
|
|
|
|
$title->getPrefixedDBKey()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-20 08:09:23 +00:00
|
|
|
public function provideCreateFragmentTitle() {
|
|
|
|
|
return [
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, 'Test' ), 'foo' ],
|
|
|
|
|
[ Title::makeTitle( NS_TALK, 'Test', 'foo' ), '' ],
|
|
|
|
|
[ Title::makeTitle( NS_CATEGORY, 'Test', 'foo' ), 'bar' ],
|
|
|
|
|
[ Title::makeTitle( NS_MAIN, 'Test1', '', 'interwiki' ), 'baz' ]
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers Title::createFragmentTarget
|
|
|
|
|
* @dataProvider provideCreateFragmentTitle
|
|
|
|
|
*/
|
|
|
|
|
public function testCreateFragmentTitle( Title $title, $fragment ) {
|
|
|
|
|
$this->mergeMwGlobalArrayValue( 'wgHooks', [
|
|
|
|
|
'InterwikiLoadPrefix' => [
|
|
|
|
|
function ( $prefix, &$iwdata ) {
|
|
|
|
|
if ( $prefix === 'interwiki' ) {
|
|
|
|
|
$iwdata = [
|
|
|
|
|
'iw_url' => 'http://example.com/',
|
|
|
|
|
'iw_local' => 0,
|
|
|
|
|
'iw_trans' => 0,
|
|
|
|
|
];
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
] );
|
|
|
|
|
|
|
|
|
|
$fragmentTitle = $title->createFragmentTarget( $fragment );
|
|
|
|
|
|
|
|
|
|
$this->assertEquals( $title->getNamespace(), $fragmentTitle->getNamespace() );
|
|
|
|
|
$this->assertEquals( $title->getText(), $fragmentTitle->getText() );
|
|
|
|
|
$this->assertEquals( $title->getInterwiki(), $fragmentTitle->getInterwiki() );
|
|
|
|
|
$this->assertEquals( $fragment, $fragmentTitle->getFragment() );
|
|
|
|
|
}
|
2016-05-12 18:14:47 +00:00
|
|
|
|
|
|
|
|
public function provideGetPrefixedText() {
|
|
|
|
|
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
|
|
|
],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers Title::getPrefixedText
|
|
|
|
|
* @dataProvider provideGetPrefixedText
|
|
|
|
|
*/
|
|
|
|
|
public function testGetPrefixedText( Title $title, $expected ) {
|
|
|
|
|
$this->assertEquals( $expected, $title->getPrefixedText() );
|
|
|
|
|
}
|
2017-06-09 16:39:33 +00:00
|
|
|
|
|
|
|
|
public function provideGetPrefixedDBKey() {
|
|
|
|
|
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'
|
|
|
|
|
],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @covers Title::getPrefixedDBKey
|
|
|
|
|
* @dataProvider provideGetPrefixedDBKey
|
|
|
|
|
*/
|
|
|
|
|
public function testGetPrefixedDBKey( Title $title, $expected ) {
|
|
|
|
|
$this->assertEquals( $expected, $title->getPrefixedDBkey() );
|
|
|
|
|
}
|
2017-11-28 23:17:46 +00:00
|
|
|
|
|
|
|
|
/**
|
2017-12-25 07:28:03 +00:00
|
|
|
* @covers Title::getFragmentForURL
|
2017-11-28 23:17:46 +00:00
|
|
|
* @dataProvider provideGetFragmentForURL
|
|
|
|
|
*
|
|
|
|
|
* @param string $titleStr
|
|
|
|
|
* @param string $expected
|
|
|
|
|
*/
|
|
|
|
|
public function testGetFragmentForURL( $titleStr, $expected ) {
|
|
|
|
|
$this->setMwGlobals( [
|
|
|
|
|
'wgFragmentMode' => [ 'html5' ],
|
|
|
|
|
'wgExternalInterwikiFragmentMode' => 'legacy',
|
|
|
|
|
] );
|
|
|
|
|
$dbw = wfGetDB( DB_MASTER );
|
|
|
|
|
$dbw->insert( 'interwiki',
|
|
|
|
|
[
|
|
|
|
|
[
|
|
|
|
|
'iw_prefix' => 'de',
|
|
|
|
|
'iw_url' => 'http://de.wikipedia.org/wiki/',
|
|
|
|
|
'iw_api' => 'http://de.wikipedia.org/w/api.php',
|
|
|
|
|
'iw_wikiid' => 'dewiki',
|
|
|
|
|
'iw_local' => 1,
|
|
|
|
|
'iw_trans' => 0,
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
'iw_prefix' => 'zz',
|
|
|
|
|
'iw_url' => 'http://zzwiki.org/wiki/',
|
|
|
|
|
'iw_api' => 'http://zzwiki.org/w/api.php',
|
|
|
|
|
'iw_wikiid' => 'zzwiki',
|
|
|
|
|
'iw_local' => 0,
|
|
|
|
|
'iw_trans' => 0,
|
|
|
|
|
],
|
|
|
|
|
],
|
|
|
|
|
__METHOD__,
|
|
|
|
|
[ 'IGNORE' ]
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$title = Title::newFromText( $titleStr );
|
|
|
|
|
self::assertEquals( $expected, $title->getFragmentForURL() );
|
|
|
|
|
|
|
|
|
|
$dbw->delete( 'interwiki', '*', __METHOD__ );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function provideGetFragmentForURL() {
|
|
|
|
|
return [
|
|
|
|
|
[ 'Foo', '' ],
|
|
|
|
|
[ 'Foo#ümlåût', '#ümlåût' ],
|
|
|
|
|
[ 'de:Foo#Bå®', '#Bå®' ],
|
|
|
|
|
[ 'zz:Foo#тест', '#.D1.82.D0.B5.D1.81.D1.82' ],
|
|
|
|
|
];
|
|
|
|
|
}
|
2010-12-14 16:26:35 +00:00
|
|
|
}
|