In the new tests I added, I tried to cover all interesting scenarios and not just hit each line to make the coverage green. But I didn't review all the existing tests to see if they were properly thorough, so there might still be room for improvement. I uncovered a bug here that will be addressed in a separate commit, because the fix is not so simple. For now I left the test expectation as a @todo. Change-Id: I33d556bf83c631a8a02a6c77f2f5cb06b8dbf869
1208 lines
33 KiB
PHP
1208 lines
33 KiB
PHP
<?php
|
||
/**
|
||
* @author Antoine Musso
|
||
* @copyright Copyright © 2011, Antoine Musso
|
||
* @file
|
||
*/
|
||
|
||
use MediaWiki\Config\ServiceOptions;
|
||
|
||
class NamespaceInfoTest extends MediaWikiTestCase {
|
||
/**********************************************************************************************
|
||
* Shared code
|
||
* %{
|
||
*/
|
||
private $scopedCallback;
|
||
|
||
public function setUp() {
|
||
parent::setUp();
|
||
|
||
// Boo, there's still some global state in the class :(
|
||
global $wgHooks;
|
||
$hooks = $wgHooks;
|
||
unset( $hooks['CanonicalNamespaces'] );
|
||
$this->setMwGlobals( 'wgHooks', $hooks );
|
||
|
||
$this->scopedCallback =
|
||
ExtensionRegistry::getInstance()->setAttributeForTest( 'ExtensionNamespaces', [] );
|
||
}
|
||
|
||
public function tearDown() {
|
||
$this->scopedCallback = null;
|
||
|
||
parent::tearDown();
|
||
}
|
||
|
||
/**
|
||
* TODO Make this a const once HHVM support is dropped (T192166)
|
||
*/
|
||
private static $defaultOptions = [
|
||
'AllowImageMoving' => true,
|
||
'CanonicalNamespaceNames' => [
|
||
NS_TALK => 'Talk',
|
||
NS_USER => 'User',
|
||
NS_USER_TALK => 'User_talk',
|
||
NS_SPECIAL => 'Special',
|
||
NS_MEDIA => 'Media',
|
||
],
|
||
'CapitalLinkOverrides' => [],
|
||
'CapitalLinks' => true,
|
||
'ContentNamespaces' => [ NS_MAIN ],
|
||
'ExtraNamespaces' => [],
|
||
'ExtraSignatureNamespaces' => [],
|
||
'NamespaceContentModels' => [],
|
||
'NamespaceProtection' => [],
|
||
'NamespacesWithSubpages' => [
|
||
NS_TALK => true,
|
||
NS_USER => true,
|
||
NS_USER_TALK => true,
|
||
],
|
||
'NonincludableNamespaces' => [],
|
||
'RestrictionLevels' => [ '', 'autoconfirmed', 'sysop' ],
|
||
];
|
||
|
||
private function newObj( array $options = [] ) : NamespaceInfo {
|
||
return new NamespaceInfo( new ServiceOptions( NamespaceInfo::$constructorOptions,
|
||
$options, self::$defaultOptions ) );
|
||
}
|
||
|
||
// %} End shared code
|
||
|
||
/**********************************************************************************************
|
||
* Basic methods
|
||
* %{
|
||
*/
|
||
|
||
/**
|
||
* @covers NamespaceInfo::__construct
|
||
* @dataProvider provideConstructor
|
||
* @param ServiceOptions $options
|
||
* @param string|null $expectedExceptionText
|
||
*/
|
||
public function testConstructor( ServiceOptions $options, $expectedExceptionText = null ) {
|
||
if ( $expectedExceptionText !== null ) {
|
||
$this->setExpectedException( \Wikimedia\Assert\PreconditionException::class,
|
||
$expectedExceptionText );
|
||
}
|
||
new NamespaceInfo( $options );
|
||
$this->assertTrue( true );
|
||
}
|
||
|
||
public function provideConstructor() {
|
||
return [
|
||
[ new ServiceOptions( NamespaceInfo::$constructorOptions, self::$defaultOptions ) ],
|
||
[ new ServiceOptions( [], [] ), 'Required options missing: ' ],
|
||
[ new ServiceOptions(
|
||
array_merge( NamespaceInfo::$constructorOptions, [ 'invalid' ] ),
|
||
self::$defaultOptions,
|
||
[ 'invalid' => '' ]
|
||
), 'Unsupported options passed: invalid' ],
|
||
];
|
||
}
|
||
|
||
/**
|
||
* @dataProvider provideIsMovable
|
||
* @covers NamespaceInfo::isMovable
|
||
*
|
||
* @param bool $expected
|
||
* @param int $ns
|
||
* @param bool $allowImageMoving
|
||
*/
|
||
public function testIsMovable( $expected, $ns, $allowImageMoving = true ) {
|
||
$obj = $this->newObj( [ 'AllowImageMoving' => $allowImageMoving ] );
|
||
$this->assertSame( $expected, $obj->isMovable( $ns ) );
|
||
}
|
||
|
||
public function provideIsMovable() {
|
||
return [
|
||
'Main' => [ true, NS_MAIN ],
|
||
'Talk' => [ true, NS_TALK ],
|
||
'Special' => [ false, NS_SPECIAL ],
|
||
'Nonexistent even namespace' => [ true, 1234 ],
|
||
'Nonexistent odd namespace' => [ true, 12345 ],
|
||
|
||
'Media with image moving' => [ false, NS_MEDIA, true ],
|
||
'Media with no image moving' => [ false, NS_MEDIA, false ],
|
||
'File with image moving' => [ true, NS_FILE, true ],
|
||
'File with no image moving' => [ false, NS_FILE, false ],
|
||
];
|
||
}
|
||
|
||
/**
|
||
* @param int $ns
|
||
* @param bool $expected
|
||
* @dataProvider provideIsSubject
|
||
* @covers NamespaceInfo::isSubject
|
||
*/
|
||
public function testIsSubject( $ns, $expected ) {
|
||
$this->assertSame( $expected, $this->newObj()->isSubject( $ns ) );
|
||
}
|
||
|
||
/**
|
||
* @param int $ns
|
||
* @param bool $expected
|
||
* @dataProvider provideIsSubject
|
||
* @covers NamespaceInfo::isTalk
|
||
*/
|
||
public function testIsTalk( $ns, $expected ) {
|
||
$this->assertSame( !$expected, $this->newObj()->isTalk( $ns ) );
|
||
}
|
||
|
||
public function provideIsSubject() {
|
||
return [
|
||
// Special namespaces
|
||
[ NS_MEDIA, true ],
|
||
[ NS_SPECIAL, true ],
|
||
|
||
// Subject pages
|
||
[ NS_MAIN, true ],
|
||
[ NS_USER, true ],
|
||
[ 100, true ],
|
||
|
||
// Talk pages
|
||
[ NS_TALK, false ],
|
||
[ NS_USER_TALK, false ],
|
||
[ 101, false ],
|
||
];
|
||
}
|
||
|
||
/**
|
||
* @covers NamespaceInfo::getSubject
|
||
*/
|
||
public function testGetSubject() {
|
||
// Special namespaces are their own subjects
|
||
$obj = $this->newObj();
|
||
$this->assertEquals( NS_MEDIA, $obj->getSubject( NS_MEDIA ) );
|
||
$this->assertEquals( NS_SPECIAL, $obj->getSubject( NS_SPECIAL ) );
|
||
|
||
$this->assertEquals( NS_MAIN, $obj->getSubject( NS_TALK ) );
|
||
$this->assertEquals( NS_USER, $obj->getSubject( NS_USER_TALK ) );
|
||
}
|
||
|
||
/**
|
||
* Regular getTalk() calls
|
||
* Namespaces without a talk page (NS_MEDIA, NS_SPECIAL) are tested in
|
||
* the function testGetTalkExceptions()
|
||
* @covers NamespaceInfo::getTalk
|
||
* @covers NamespaceInfo::isMethodValidFor
|
||
*/
|
||
public function testGetTalk() {
|
||
$obj = $this->newObj();
|
||
$this->assertEquals( NS_TALK, $obj->getTalk( NS_MAIN ) );
|
||
$this->assertEquals( NS_TALK, $obj->getTalk( NS_TALK ) );
|
||
$this->assertEquals( NS_USER_TALK, $obj->getTalk( NS_USER ) );
|
||
$this->assertEquals( NS_USER_TALK, $obj->getTalk( NS_USER_TALK ) );
|
||
}
|
||
|
||
/**
|
||
* Exceptions with getTalk()
|
||
* NS_MEDIA does not have talk pages. MediaWiki raise an exception for them.
|
||
* @expectedException MWException
|
||
* @covers NamespaceInfo::getTalk
|
||
* @covers NamespaceInfo::isMethodValidFor
|
||
*/
|
||
public function testGetTalkExceptionsForNsMedia() {
|
||
$this->assertNull( $this->newObj()->getTalk( NS_MEDIA ) );
|
||
}
|
||
|
||
/**
|
||
* Exceptions with getTalk()
|
||
* NS_SPECIAL does not have talk pages. MediaWiki raise an exception for them.
|
||
* @expectedException MWException
|
||
* @covers NamespaceInfo::getTalk
|
||
*/
|
||
public function testGetTalkExceptionsForNsSpecial() {
|
||
$this->assertNull( $this->newObj()->getTalk( NS_SPECIAL ) );
|
||
}
|
||
|
||
/**
|
||
* Regular getAssociated() calls
|
||
* Namespaces without an associated page (NS_MEDIA, NS_SPECIAL) are tested in
|
||
* the function testGetAssociatedExceptions()
|
||
* @covers NamespaceInfo::getAssociated
|
||
*/
|
||
public function testGetAssociated() {
|
||
$this->assertEquals( NS_TALK, $this->newObj()->getAssociated( NS_MAIN ) );
|
||
$this->assertEquals( NS_MAIN, $this->newObj()->getAssociated( NS_TALK ) );
|
||
}
|
||
|
||
# ## Exceptions with getAssociated()
|
||
# ## NS_MEDIA and NS_SPECIAL do not have talk pages. MediaWiki raises
|
||
# ## an exception for them.
|
||
/**
|
||
* @expectedException MWException
|
||
* @covers NamespaceInfo::getAssociated
|
||
*/
|
||
public function testGetAssociatedExceptionsForNsMedia() {
|
||
$this->assertNull( $this->newObj()->getAssociated( NS_MEDIA ) );
|
||
}
|
||
|
||
/**
|
||
* @expectedException MWException
|
||
* @covers NamespaceInfo::getAssociated
|
||
*/
|
||
public function testGetAssociatedExceptionsForNsSpecial() {
|
||
$this->assertNull( $this->newObj()->getAssociated( NS_SPECIAL ) );
|
||
}
|
||
|
||
/**
|
||
* @covers NamespaceInfo::exists
|
||
* @dataProvider provideExists
|
||
* @param int $ns
|
||
* @param bool $expected
|
||
*/
|
||
public function testExists( $ns, $expected ) {
|
||
$this->assertSame( $expected, $this->newObj()->exists( $ns ) );
|
||
}
|
||
|
||
public function provideExists() {
|
||
return [
|
||
'Main' => [ NS_MAIN, true ],
|
||
'Talk' => [ NS_TALK, true ],
|
||
'Media' => [ NS_MEDIA, true ],
|
||
'Special' => [ NS_SPECIAL, true ],
|
||
'Nonexistent' => [ 12345, false ],
|
||
'Negative nonexistent' => [ -12345, false ],
|
||
];
|
||
}
|
||
|
||
/**
|
||
* Note if we add a namespace registration system with keys like 'MAIN'
|
||
* we should add tests here for equivalence on things like 'MAIN' == 0
|
||
* and 'MAIN' == NS_MAIN.
|
||
* @covers NamespaceInfo::equals
|
||
*/
|
||
public function testEquals() {
|
||
$obj = $this->newObj();
|
||
$this->assertTrue( $obj->equals( NS_MAIN, NS_MAIN ) );
|
||
$this->assertTrue( $obj->equals( NS_MAIN, 0 ) ); // In case we make NS_MAIN 'MAIN'
|
||
$this->assertTrue( $obj->equals( NS_USER, NS_USER ) );
|
||
$this->assertTrue( $obj->equals( NS_USER, 2 ) );
|
||
$this->assertTrue( $obj->equals( NS_USER_TALK, NS_USER_TALK ) );
|
||
$this->assertTrue( $obj->equals( NS_SPECIAL, NS_SPECIAL ) );
|
||
$this->assertFalse( $obj->equals( NS_MAIN, NS_TALK ) );
|
||
$this->assertFalse( $obj->equals( NS_USER, NS_USER_TALK ) );
|
||
$this->assertFalse( $obj->equals( NS_PROJECT, NS_TEMPLATE ) );
|
||
}
|
||
|
||
/**
|
||
* @param int $ns1
|
||
* @param int $ns2
|
||
* @param bool $expected
|
||
* @dataProvider provideSubjectEquals
|
||
* @covers NamespaceInfo::subjectEquals
|
||
*/
|
||
public function testSubjectEquals( $ns1, $ns2, $expected ) {
|
||
$this->assertSame( $expected, $this->newObj()->subjectEquals( $ns1, $ns2 ) );
|
||
}
|
||
|
||
public function provideSubjectEquals() {
|
||
return [
|
||
[ NS_MAIN, NS_MAIN, true ],
|
||
// In case we make NS_MAIN 'MAIN'
|
||
[ NS_MAIN, 0, true ],
|
||
[ NS_USER, NS_USER, true ],
|
||
[ NS_USER, 2, true ],
|
||
[ NS_USER_TALK, NS_USER_TALK, true ],
|
||
[ NS_SPECIAL, NS_SPECIAL, true ],
|
||
[ NS_MAIN, NS_TALK, true ],
|
||
[ NS_USER, NS_USER_TALK, true ],
|
||
|
||
[ NS_PROJECT, NS_TEMPLATE, false ],
|
||
[ NS_SPECIAL, NS_MAIN, false ],
|
||
[ NS_MEDIA, NS_SPECIAL, false ],
|
||
[ NS_SPECIAL, NS_MEDIA, false ],
|
||
];
|
||
}
|
||
|
||
/**
|
||
* @dataProvider provideHasTalkNamespace
|
||
* @covers NamespaceInfo::hasTalkNamespace
|
||
*
|
||
* @param int $ns
|
||
* @param bool $expected
|
||
*/
|
||
public function testHasTalkNamespace( $ns, $expected ) {
|
||
$this->assertSame( $expected, $this->newObj()->hasTalkNamespace( $ns ) );
|
||
}
|
||
|
||
public function provideHasTalkNamespace() {
|
||
return [
|
||
[ NS_MEDIA, false ],
|
||
[ NS_SPECIAL, false ],
|
||
|
||
[ NS_MAIN, true ],
|
||
[ NS_TALK, true ],
|
||
[ NS_USER, true ],
|
||
[ NS_USER_TALK, true ],
|
||
|
||
[ 100, true ],
|
||
[ 101, true ],
|
||
];
|
||
}
|
||
|
||
/**
|
||
* @param int $ns
|
||
* @param bool $expected
|
||
* @param array $contentNamespaces
|
||
* @covers NamespaceInfo::isContent
|
||
* @dataProvider provideIsContent
|
||
*/
|
||
public function testIsContent( $ns, $expected, $contentNamespaces = [ NS_MAIN ] ) {
|
||
$obj = $this->newObj( [ 'ContentNamespaces' => $contentNamespaces ] );
|
||
$this->assertSame( $expected, $obj->isContent( $ns ) );
|
||
}
|
||
|
||
public function provideIsContent() {
|
||
return [
|
||
[ NS_MAIN, true ],
|
||
[ NS_MEDIA, false ],
|
||
[ NS_SPECIAL, false ],
|
||
[ NS_TALK, false ],
|
||
[ NS_USER, false ],
|
||
[ NS_CATEGORY, false ],
|
||
[ 100, false ],
|
||
[ 100, true, [ NS_MAIN, 100, 252 ] ],
|
||
[ 252, true, [ NS_MAIN, 100, 252 ] ],
|
||
[ NS_MAIN, true, [ NS_MAIN, 100, 252 ] ],
|
||
// NS_MAIN is always content
|
||
[ NS_MAIN, true, [] ],
|
||
];
|
||
}
|
||
|
||
/**
|
||
* @dataProvider provideWantSignatures
|
||
* @covers NamespaceInfo::wantSignatures
|
||
*
|
||
* @param int $index
|
||
* @param bool $expected
|
||
*/
|
||
public function testWantSignatures( $index, $expected ) {
|
||
$this->assertSame( $expected, $this->newObj()->wantSignatures( $index ) );
|
||
}
|
||
|
||
public function provideWantSignatures() {
|
||
return [
|
||
'Main' => [ NS_MAIN, false ],
|
||
'Talk' => [ NS_TALK, true ],
|
||
'User' => [ NS_USER, false ],
|
||
'User talk' => [ NS_USER_TALK, true ],
|
||
'Special' => [ NS_SPECIAL, false ],
|
||
'Media' => [ NS_MEDIA, false ],
|
||
'Nonexistent talk' => [ 12345, true ],
|
||
'Nonexistent subject' => [ 123456, false ],
|
||
'Nonexistent negative odd' => [ -12345, false ],
|
||
];
|
||
}
|
||
|
||
/**
|
||
* @dataProvider provideWantSignatures_ExtraSignatureNamespaces
|
||
* @covers NamespaceInfo::wantSignatures
|
||
*
|
||
* @param int $index
|
||
* @param int $expected
|
||
*/
|
||
public function testWantSignatures_ExtraSignatureNamespaces( $index, $expected ) {
|
||
$obj = $this->newObj( [ 'ExtraSignatureNamespaces' =>
|
||
[ NS_MAIN, NS_USER, NS_SPECIAL, NS_MEDIA, 123456, -12345 ] ] );
|
||
$this->assertSame( $expected, $obj->wantSignatures( $index ) );
|
||
}
|
||
|
||
public function provideWantSignatures_ExtraSignatureNamespaces() {
|
||
$ret = array_map(
|
||
function ( $arr ) {
|
||
// We've added all these as extra signature namespaces, so expect true
|
||
return [ $arr[0], true ];
|
||
},
|
||
self::provideWantSignatures()
|
||
);
|
||
|
||
// Add one more that's false
|
||
$ret['Another nonexistent subject'] = [ 12345678, false ];
|
||
return $ret;
|
||
}
|
||
|
||
/**
|
||
* @param int $ns
|
||
* @param bool $expected
|
||
* @covers NamespaceInfo::isWatchable
|
||
* @dataProvider provideIsWatchable
|
||
*/
|
||
public function testIsWatchable( $ns, $expected ) {
|
||
$this->assertSame( $expected, $this->newObj()->isWatchable( $ns ) );
|
||
}
|
||
|
||
public function provideIsWatchable() {
|
||
return [
|
||
// Specials namespaces are not watchable
|
||
[ NS_MEDIA, false ],
|
||
[ NS_SPECIAL, false ],
|
||
|
||
// Core defined namespaces are watchables
|
||
[ NS_MAIN, true ],
|
||
[ NS_TALK, true ],
|
||
|
||
// Additional, user defined namespaces are watchables
|
||
[ 100, true ],
|
||
[ 101, true ],
|
||
];
|
||
}
|
||
|
||
/**
|
||
* @param int $ns
|
||
* @param int $expected
|
||
* @param array|null $namespacesWithSubpages To pass to constructor
|
||
* @covers NamespaceInfo::hasSubpages
|
||
* @dataProvider provideHasSubpages
|
||
*/
|
||
public function testHasSubpages( $ns, $expected, array $namespacesWithSubpages = null ) {
|
||
$obj = $this->newObj( $namespacesWithSubpages
|
||
? [ 'NamespacesWithSubpages' => $namespacesWithSubpages ]
|
||
: [] );
|
||
$this->assertSame( $expected, $obj->hasSubpages( $ns ) );
|
||
}
|
||
|
||
public function provideHasSubpages() {
|
||
return [
|
||
// Special namespaces:
|
||
[ NS_MEDIA, false ],
|
||
[ NS_SPECIAL, false ],
|
||
|
||
// Namespaces without subpages
|
||
[ NS_MAIN, false ],
|
||
[ NS_MAIN, true, [ NS_MAIN => true ] ],
|
||
[ NS_MAIN, false, [ NS_MAIN => false ] ],
|
||
|
||
// Some namespaces with subpages
|
||
[ NS_TALK, true ],
|
||
[ NS_USER, true ],
|
||
[ NS_USER_TALK, true ],
|
||
];
|
||
}
|
||
|
||
/**
|
||
* @param $contentNamespaces To pass to constructor
|
||
* @param array $expected
|
||
* @dataProvider provideGetContentNamespaces
|
||
* @covers NamespaceInfo::getContentNamespaces
|
||
*/
|
||
public function testGetContentNamespaces( $contentNamespaces, array $expected ) {
|
||
$obj = $this->newObj( [ 'ContentNamespaces' => $contentNamespaces ] );
|
||
$this->assertSame( $expected, $obj->getContentNamespaces() );
|
||
}
|
||
|
||
public function provideGetContentNamespaces() {
|
||
return [
|
||
// Non-array
|
||
[ '', [ NS_MAIN ] ],
|
||
[ false, [ NS_MAIN ] ],
|
||
[ null, [ NS_MAIN ] ],
|
||
[ 5, [ NS_MAIN ] ],
|
||
|
||
// Empty array
|
||
[ [], [ NS_MAIN ] ],
|
||
|
||
// NS_MAIN is forced to be content even if unwanted
|
||
[ [ NS_USER, NS_CATEGORY ], [ NS_MAIN, NS_USER, NS_CATEGORY ] ],
|
||
|
||
// In other cases, return as-is
|
||
[ [ NS_MAIN ], [ NS_MAIN ] ],
|
||
[ [ NS_MAIN, NS_USER, NS_CATEGORY ], [ NS_MAIN, NS_USER, NS_CATEGORY ] ],
|
||
];
|
||
}
|
||
|
||
/**
|
||
* @covers NamespaceInfo::getSubjectNamespaces
|
||
*/
|
||
public function testGetSubjectNamespaces() {
|
||
$subjectsNS = $this->newObj()->getSubjectNamespaces();
|
||
$this->assertContains( NS_MAIN, $subjectsNS,
|
||
"Talk namespaces should have NS_MAIN" );
|
||
$this->assertNotContains( NS_TALK, $subjectsNS,
|
||
"Talk namespaces should have NS_TALK" );
|
||
|
||
$this->assertNotContains( NS_MEDIA, $subjectsNS,
|
||
"Talk namespaces should not have NS_MEDIA" );
|
||
$this->assertNotContains( NS_SPECIAL, $subjectsNS,
|
||
"Talk namespaces should not have NS_SPECIAL" );
|
||
}
|
||
|
||
/**
|
||
* @covers NamespaceInfo::getTalkNamespaces
|
||
*/
|
||
public function testGetTalkNamespaces() {
|
||
$talkNS = $this->newObj()->getTalkNamespaces();
|
||
$this->assertContains( NS_TALK, $talkNS,
|
||
"Subject namespaces should have NS_TALK" );
|
||
$this->assertNotContains( NS_MAIN, $talkNS,
|
||
"Subject namespaces should not have NS_MAIN" );
|
||
|
||
$this->assertNotContains( NS_MEDIA, $talkNS,
|
||
"Subject namespaces should not have NS_MEDIA" );
|
||
$this->assertNotContains( NS_SPECIAL, $talkNS,
|
||
"Subject namespaces should not have NS_SPECIAL" );
|
||
}
|
||
|
||
/**
|
||
* @param int $ns
|
||
* @param bool $expected
|
||
* @param bool $capitalLinks To pass to constructor
|
||
* @param array $capitalLinkOverrides To pass to constructor
|
||
* @dataProvider provideIsCapitalized
|
||
* @covers NamespaceInfo::isCapitalized
|
||
*/
|
||
public function testIsCapitalized(
|
||
$ns, $expected, $capitalLinks = true, array $capitalLinkOverrides = []
|
||
) {
|
||
$obj = $this->newObj( [
|
||
'CapitalLinks' => $capitalLinks,
|
||
'CapitalLinkOverrides' => $capitalLinkOverrides,
|
||
] );
|
||
$this->assertSame( $expected, $obj->isCapitalized( $ns ) );
|
||
}
|
||
|
||
public function provideIsCapitalized() {
|
||
return [
|
||
// Test default settings
|
||
[ NS_PROJECT, true ],
|
||
[ NS_PROJECT_TALK, true ],
|
||
[ NS_MEDIA, true ],
|
||
[ NS_FILE, true ],
|
||
|
||
// Always capitalized no matter what
|
||
[ NS_SPECIAL, true, false ],
|
||
[ NS_USER, true, false ],
|
||
[ NS_MEDIAWIKI, true, false ],
|
||
|
||
// Even with an override too
|
||
[ NS_SPECIAL, true, false, [ NS_SPECIAL => false ] ],
|
||
[ NS_USER, true, false, [ NS_USER => false ] ],
|
||
[ NS_MEDIAWIKI, true, false, [ NS_MEDIAWIKI => false ] ],
|
||
|
||
// Overrides work for other namespaces
|
||
[ NS_PROJECT, false, true, [ NS_PROJECT => false ] ],
|
||
[ NS_PROJECT, true, false, [ NS_PROJECT => true ] ],
|
||
|
||
// NS_MEDIA is treated like NS_FILE, and ignores NS_MEDIA overrides
|
||
[ NS_MEDIA, false, true, [ NS_FILE => false, NS_MEDIA => true ] ],
|
||
[ NS_MEDIA, true, false, [ NS_FILE => true, NS_MEDIA => false ] ],
|
||
[ NS_FILE, false, true, [ NS_FILE => false, NS_MEDIA => true ] ],
|
||
[ NS_FILE, true, false, [ NS_FILE => true, NS_MEDIA => false ] ],
|
||
];
|
||
}
|
||
|
||
/**
|
||
* @covers NamespaceInfo::hasGenderDistinction
|
||
*/
|
||
public function testHasGenderDistinction() {
|
||
$obj = $this->newObj();
|
||
|
||
// Namespaces with gender distinctions
|
||
$this->assertTrue( $obj->hasGenderDistinction( NS_USER ) );
|
||
$this->assertTrue( $obj->hasGenderDistinction( NS_USER_TALK ) );
|
||
|
||
// Other ones, "genderless"
|
||
$this->assertFalse( $obj->hasGenderDistinction( NS_MEDIA ) );
|
||
$this->assertFalse( $obj->hasGenderDistinction( NS_SPECIAL ) );
|
||
$this->assertFalse( $obj->hasGenderDistinction( NS_MAIN ) );
|
||
$this->assertFalse( $obj->hasGenderDistinction( NS_TALK ) );
|
||
}
|
||
|
||
/**
|
||
* @covers NamespaceInfo::isNonincludable
|
||
*/
|
||
public function testIsNonincludable() {
|
||
$obj = $this->newObj( [ 'NonincludableNamespaces' => [ NS_USER ] ] );
|
||
$this->assertTrue( $obj->isNonincludable( NS_USER ) );
|
||
$this->assertFalse( $obj->isNonincludable( NS_TEMPLATE ) );
|
||
}
|
||
|
||
/**
|
||
* @dataProvider provideGetNamespaceContentModel
|
||
* @covers NamespaceInfo::getNamespaceContentModel
|
||
*
|
||
* @param int $ns
|
||
* @param string $expected
|
||
*/
|
||
public function testGetNamespaceContentModel( $ns, $expected ) {
|
||
$obj = $this->newObj( [ 'NamespaceContentModels' =>
|
||
[ NS_USER => CONTENT_MODEL_WIKITEXT, 123 => CONTENT_MODEL_JSON, 1234 => 'abcdef' ],
|
||
] );
|
||
$this->assertSame( $expected, $obj->getNamespaceContentModel( $ns ) );
|
||
}
|
||
|
||
public function provideGetNamespaceContentModel() {
|
||
return [
|
||
[ NS_MAIN, null ],
|
||
[ NS_TALK, null ],
|
||
[ NS_USER, CONTENT_MODEL_WIKITEXT ],
|
||
[ NS_USER_TALK, null ],
|
||
[ NS_SPECIAL, null ],
|
||
[ 122, null ],
|
||
[ 123, CONTENT_MODEL_JSON ],
|
||
[ 1234, 'abcdef' ],
|
||
[ 1235, null ],
|
||
];
|
||
}
|
||
|
||
/**
|
||
* @dataProvider provideGetCategoryLinkType
|
||
* @covers NamespaceInfo::getCategoryLinkType
|
||
*
|
||
* @param int $ns
|
||
* @param string $expected
|
||
*/
|
||
public function testGetCategoryLinkType( $ns, $expected ) {
|
||
$this->assertSame( $expected, $this->newObj()->getCategoryLinkType( $ns ) );
|
||
}
|
||
|
||
public function provideGetCategoryLinkType() {
|
||
return [
|
||
[ NS_MAIN, 'page' ],
|
||
[ NS_TALK, 'page' ],
|
||
[ NS_USER, 'page' ],
|
||
[ NS_USER_TALK, 'page' ],
|
||
|
||
[ NS_FILE, 'file' ],
|
||
[ NS_FILE_TALK, 'page' ],
|
||
|
||
[ NS_CATEGORY, 'subcat' ],
|
||
[ NS_CATEGORY_TALK, 'page' ],
|
||
|
||
[ 100, 'page' ],
|
||
[ 101, 'page' ],
|
||
];
|
||
}
|
||
|
||
// %} End basic methods
|
||
|
||
/**********************************************************************************************
|
||
* Canonical namespaces
|
||
* %{
|
||
*/
|
||
|
||
// Default canonical namespaces
|
||
// %{
|
||
private function getDefaultNamespaces() {
|
||
return [ NS_MAIN => '' ] + self::$defaultOptions['CanonicalNamespaceNames'];
|
||
}
|
||
|
||
/**
|
||
* @covers NamespaceInfo::getCanonicalNamespaces
|
||
*/
|
||
public function testGetCanonicalNamespaces() {
|
||
$this->assertSame(
|
||
$this->getDefaultNamespaces(),
|
||
$this->newObj()->getCanonicalNamespaces()
|
||
);
|
||
}
|
||
|
||
/**
|
||
* @dataProvider provideGetCanonicalName
|
||
* @covers NamespaceInfo::getCanonicalName
|
||
*
|
||
* @param int $index
|
||
* @param string|bool $expected
|
||
*/
|
||
public function testGetCanonicalName( $index, $expected ) {
|
||
$this->assertSame( $expected, $this->newObj()->getCanonicalName( $index ) );
|
||
}
|
||
|
||
public function provideGetCanonicalName() {
|
||
return [
|
||
'Main' => [ NS_MAIN, '' ],
|
||
'Talk' => [ NS_TALK, 'Talk' ],
|
||
'With underscore not space' => [ NS_USER_TALK, 'User_talk' ],
|
||
'Special' => [ NS_SPECIAL, 'Special' ],
|
||
'Nonexistent' => [ 12345, false ],
|
||
'Nonexistent negative' => [ -12345, false ],
|
||
];
|
||
}
|
||
|
||
/**
|
||
* @dataProvider provideGetCanonicalIndex
|
||
* @covers NamespaceInfo::getCanonicalIndex
|
||
*
|
||
* @param string $name
|
||
* @param int|null $expected
|
||
*/
|
||
public function testGetCanonicalIndex( $name, $expected ) {
|
||
$this->assertSame( $expected, $this->newObj()->getCanonicalIndex( $name ) );
|
||
}
|
||
|
||
public function provideGetCanonicalIndex() {
|
||
return [
|
||
'Main' => [ '', NS_MAIN ],
|
||
'Talk' => [ 'talk', NS_TALK ],
|
||
'Not lowercase' => [ 'Talk', null ],
|
||
'With underscore' => [ 'user_talk', NS_USER_TALK ],
|
||
'Space is not recognized for underscore' => [ 'user talk', null ],
|
||
'0' => [ '0', null ],
|
||
];
|
||
}
|
||
|
||
/**
|
||
* @covers NamespaceInfo::getValidNamespaces
|
||
*/
|
||
public function testGetValidNamespaces() {
|
||
$this->assertSame(
|
||
[ NS_MAIN, NS_TALK, NS_USER, NS_USER_TALK ],
|
||
$this->newObj()->getValidNamespaces()
|
||
);
|
||
}
|
||
|
||
// %} End default canonical namespaces
|
||
|
||
// No canonical namespace names
|
||
// %{
|
||
/**
|
||
* @covers NamespaceInfo::getCanonicalNamespaces
|
||
*/
|
||
public function testGetCanonicalNamespaces_NoCanonicalNamespaceNames() {
|
||
$obj = $this->newObj( [ 'CanonicalNamespaceNames' => [] ] );
|
||
|
||
$this->assertSame( [ NS_MAIN => '' ], $obj->getCanonicalNamespaces() );
|
||
}
|
||
|
||
/**
|
||
* @covers NamespaceInfo::getCanonicalName
|
||
*/
|
||
public function testGetCanonicalName_NoCanonicalNamespaceNames() {
|
||
$obj = $this->newObj( [ 'CanonicalNamespaceNames' => [] ] );
|
||
|
||
$this->assertSame( '', $obj->getCanonicalName( NS_MAIN ) );
|
||
$this->assertFalse( $obj->getCanonicalName( NS_TALK ) );
|
||
}
|
||
|
||
/**
|
||
* @covers NamespaceInfo::getCanonicalIndex
|
||
*/
|
||
public function testGetCanonicalIndex_NoCanonicalNamespaceNames() {
|
||
$obj = $this->newObj( [ 'CanonicalNamespaceNames' => [] ] );
|
||
|
||
$this->assertSame( NS_MAIN, $obj->getCanonicalIndex( '' ) );
|
||
$this->assertNull( $obj->getCanonicalIndex( 'talk' ) );
|
||
}
|
||
|
||
/**
|
||
* @covers NamespaceInfo::getValidNamespaces
|
||
*/
|
||
public function testGetValidNamespaces_NoCanonicalNamespaceNames() {
|
||
$obj = $this->newObj( [ 'CanonicalNamespaceNames' => [] ] );
|
||
|
||
$this->assertSame( [ NS_MAIN ], $obj->getValidNamespaces() );
|
||
}
|
||
|
||
// %} End no canonical namespace names
|
||
|
||
// Test extension namespaces
|
||
// %{
|
||
private function setupExtensionNamespaces() {
|
||
$this->scopedCallback = null;
|
||
$this->scopedCallback = ExtensionRegistry::getInstance()->setAttributeForTest(
|
||
'ExtensionNamespaces',
|
||
[ NS_MAIN => 'No effect', NS_TALK => 'No effect', 12345 => 'Extended' ]
|
||
);
|
||
}
|
||
|
||
/**
|
||
* @covers NamespaceInfo::getCanonicalNamespaces
|
||
*/
|
||
public function testGetCanonicalNamespaces_ExtensionNamespaces() {
|
||
$this->setupExtensionNamespaces();
|
||
|
||
$this->assertSame(
|
||
$this->getDefaultNamespaces() + [ 12345 => 'Extended' ],
|
||
$this->newObj()->getCanonicalNamespaces()
|
||
);
|
||
}
|
||
|
||
/**
|
||
* @covers NamespaceInfo::getCanonicalName
|
||
*/
|
||
public function testGetCanonicalName_ExtensionNamespaces() {
|
||
$this->setupExtensionNamespaces();
|
||
$obj = $this->newObj();
|
||
|
||
$this->assertSame( '', $obj->getCanonicalName( NS_MAIN ) );
|
||
$this->assertSame( 'Talk', $obj->getCanonicalName( NS_TALK ) );
|
||
$this->assertSame( 'Extended', $obj->getCanonicalName( 12345 ) );
|
||
}
|
||
|
||
/**
|
||
* @covers NamespaceInfo::getCanonicalIndex
|
||
*/
|
||
public function testGetCanonicalIndex_ExtensionNamespaces() {
|
||
$this->setupExtensionNamespaces();
|
||
$obj = $this->newObj();
|
||
|
||
$this->assertSame( NS_MAIN, $obj->getCanonicalIndex( '' ) );
|
||
$this->assertSame( NS_TALK, $obj->getCanonicalIndex( 'talk' ) );
|
||
$this->assertSame( 12345, $obj->getCanonicalIndex( 'extended' ) );
|
||
}
|
||
|
||
/**
|
||
* @covers NamespaceInfo::getValidNamespaces
|
||
*/
|
||
public function testGetValidNamespaces_ExtensionNamespaces() {
|
||
$this->setupExtensionNamespaces();
|
||
|
||
$this->assertSame(
|
||
[ NS_MAIN, NS_TALK, NS_USER, NS_USER_TALK, 12345 ],
|
||
$this->newObj()->getValidNamespaces()
|
||
);
|
||
}
|
||
|
||
// %} End extension namespaces
|
||
|
||
// Hook namespaces
|
||
// %{
|
||
/**
|
||
* @return array Expected canonical namespaces
|
||
*/
|
||
private function setupHookNamespaces() {
|
||
$callback =
|
||
function ( &$canonicalNamespaces ) {
|
||
$canonicalNamespaces[NS_MAIN] = 'Main';
|
||
unset( $canonicalNamespaces[NS_MEDIA] );
|
||
$canonicalNamespaces[123456] = 'Hooked';
|
||
};
|
||
$this->setTemporaryHook( 'CanonicalNamespaces', $callback );
|
||
$expected = $this->getDefaultNamespaces();
|
||
( $callback )( $expected );
|
||
return $expected;
|
||
}
|
||
|
||
/**
|
||
* @covers NamespaceInfo::getCanonicalNamespaces
|
||
*/
|
||
public function testGetCanonicalNamespaces_HookNamespaces() {
|
||
$expected = $this->setupHookNamespaces();
|
||
|
||
$this->assertSame( $expected, $this->newObj()->getCanonicalNamespaces() );
|
||
}
|
||
|
||
/**
|
||
* @covers NamespaceInfo::getCanonicalName
|
||
*/
|
||
public function testGetCanonicalName_HookNamespaces() {
|
||
$this->setupHookNamespaces();
|
||
$obj = $this->newObj();
|
||
|
||
$this->assertSame( 'Main', $obj->getCanonicalName( NS_MAIN ) );
|
||
$this->assertFalse( $obj->getCanonicalName( NS_MEDIA ) );
|
||
$this->assertSame( 'Hooked', $obj->getCanonicalName( 123456 ) );
|
||
}
|
||
|
||
/**
|
||
* @covers NamespaceInfo::getCanonicalIndex
|
||
*/
|
||
public function testGetCanonicalIndex_HookNamespaces() {
|
||
$this->setupHookNamespaces();
|
||
$obj = $this->newObj();
|
||
|
||
$this->assertSame( NS_MAIN, $obj->getCanonicalIndex( 'main' ) );
|
||
$this->assertNull( $obj->getCanonicalIndex( 'media' ) );
|
||
$this->assertSame( 123456, $obj->getCanonicalIndex( 'hooked' ) );
|
||
}
|
||
|
||
/**
|
||
* @covers NamespaceInfo::getValidNamespaces
|
||
*/
|
||
public function testGetValidNamespaces_HookNamespaces() {
|
||
$this->setupHookNamespaces();
|
||
|
||
$this->assertSame(
|
||
[ NS_MAIN, NS_TALK, NS_USER, NS_USER_TALK, 123456 ],
|
||
$this->newObj()->getValidNamespaces()
|
||
);
|
||
}
|
||
|
||
// %} End hook namespaces
|
||
|
||
// Extra namespaces
|
||
// %{
|
||
/**
|
||
* @return NamespaceInfo
|
||
*/
|
||
private function setupExtraNamespaces() {
|
||
return $this->newObj( [ 'ExtraNamespaces' =>
|
||
[ NS_MAIN => 'No effect', NS_TALK => 'No effect', 1234567 => 'Extra' ]
|
||
] );
|
||
}
|
||
|
||
/**
|
||
* @covers NamespaceInfo::getCanonicalNamespaces
|
||
*/
|
||
public function testGetCanonicalNamespaces_ExtraNamespaces() {
|
||
$this->assertSame(
|
||
$this->getDefaultNamespaces() + [ 1234567 => 'Extra' ],
|
||
$this->setupExtraNamespaces()->getCanonicalNamespaces()
|
||
);
|
||
}
|
||
|
||
/**
|
||
* @covers NamespaceInfo::getCanonicalName
|
||
*/
|
||
public function testGetCanonicalName_ExtraNamespaces() {
|
||
$obj = $this->setupExtraNamespaces();
|
||
|
||
$this->assertSame( '', $obj->getCanonicalName( NS_MAIN ) );
|
||
$this->assertSame( 'Talk', $obj->getCanonicalName( NS_TALK ) );
|
||
$this->assertSame( 'Extra', $obj->getCanonicalName( 1234567 ) );
|
||
}
|
||
|
||
/**
|
||
* @covers NamespaceInfo::getCanonicalIndex
|
||
*/
|
||
public function testGetCanonicalIndex_ExtraNamespaces() {
|
||
$obj = $this->setupExtraNamespaces();
|
||
|
||
$this->assertNull( $obj->getCanonicalIndex( 'no effect' ) );
|
||
$this->assertNull( $obj->getCanonicalIndex( 'no_effect' ) );
|
||
$this->assertSame( 1234567, $obj->getCanonicalIndex( 'extra' ) );
|
||
}
|
||
|
||
/**
|
||
* @covers NamespaceInfo::getValidNamespaces
|
||
*/
|
||
public function testGetValidNamespaces_ExtraNamespaces() {
|
||
$this->assertSame(
|
||
[ NS_MAIN, NS_TALK, NS_USER, NS_USER_TALK, 1234567 ],
|
||
$this->setupExtraNamespaces()->getValidNamespaces()
|
||
);
|
||
}
|
||
|
||
// %} End extra namespaces
|
||
|
||
// Canonical namespace caching
|
||
// %{
|
||
/**
|
||
* @covers NamespaceInfo::getCanonicalNamespaces
|
||
*/
|
||
public function testGetCanonicalNamespaces_caching() {
|
||
$obj = $this->newObj();
|
||
|
||
// This should cache the values
|
||
$obj->getCanonicalNamespaces();
|
||
|
||
// Now try to alter them through nefarious means
|
||
$this->setupExtensionNamespaces();
|
||
$this->setupHookNamespaces();
|
||
|
||
// Should have no effect
|
||
$this->assertSame( $this->getDefaultNamespaces(), $obj->getCanonicalNamespaces() );
|
||
}
|
||
|
||
/**
|
||
* @covers NamespaceInfo::getCanonicalName
|
||
*/
|
||
public function testGetCanonicalName_caching() {
|
||
$obj = $this->newObj();
|
||
|
||
// This should cache the values
|
||
$obj->getCanonicalName( NS_MAIN );
|
||
|
||
// Now try to alter them through nefarious means
|
||
$this->setupExtensionNamespaces();
|
||
$this->setupHookNamespaces();
|
||
|
||
// Should have no effect
|
||
$this->assertSame( '', $obj->getCanonicalName( NS_MAIN ) );
|
||
$this->assertSame( 'Media', $obj->getCanonicalName( NS_MEDIA ) );
|
||
$this->assertFalse( $obj->getCanonicalName( 12345 ) );
|
||
$this->assertFalse( $obj->getCanonicalName( 123456 ) );
|
||
}
|
||
|
||
/**
|
||
* @covers NamespaceInfo::getCanonicalIndex
|
||
*/
|
||
public function testGetCanonicalIndex_caching() {
|
||
$obj = $this->newObj();
|
||
|
||
// This should cache the values
|
||
$obj->getCanonicalIndex( '' );
|
||
|
||
// Now try to alter them through nefarious means
|
||
$this->setupExtensionNamespaces();
|
||
$this->setupHookNamespaces();
|
||
|
||
// Should have no effect
|
||
$this->assertSame( NS_MAIN, $obj->getCanonicalIndex( '' ) );
|
||
$this->assertSame( NS_MEDIA, $obj->getCanonicalIndex( 'media' ) );
|
||
$this->assertNull( $obj->getCanonicalIndex( 'extended' ) );
|
||
$this->assertNull( $obj->getCanonicalIndex( 'hooked' ) );
|
||
}
|
||
|
||
/**
|
||
* @covers NamespaceInfo::getValidNamespaces
|
||
*/
|
||
public function testGetValidNamespaces_caching() {
|
||
$obj = $this->newObj();
|
||
|
||
// This should cache the values
|
||
$obj->getValidNamespaces();
|
||
|
||
// Now try to alter through nefarious means
|
||
$this->setupExtensionNamespaces();
|
||
$this->setupHookNamespaces();
|
||
|
||
// Should have no effect
|
||
$this->assertSame(
|
||
[ NS_MAIN, NS_TALK, NS_USER, NS_USER_TALK ],
|
||
$obj->getValidNamespaces()
|
||
);
|
||
}
|
||
|
||
// %} End canonical namespace caching
|
||
|
||
// Miscellaneous
|
||
// %{
|
||
|
||
/**
|
||
* @dataProvider provideGetValidNamespaces_misc
|
||
* @covers NamespaceInfo::getValidNamespaces
|
||
*
|
||
* @param array $namespaces List of namespace indices to return from getCanonicalNamespaces()
|
||
* (list is overwritten by a hook, so NS_MAIN doesn't have to be present)
|
||
* @param array $expected
|
||
*/
|
||
public function testGetValidNamespaces_misc( array $namespaces, array $expected ) {
|
||
// Each namespace's name is just its index
|
||
$this->setTemporaryHook( 'CanonicalNamespaces',
|
||
function ( &$canonicalNamespaces ) use ( $namespaces ) {
|
||
$canonicalNamespaces = array_combine( $namespaces, $namespaces );
|
||
}
|
||
);
|
||
$this->assertSame( $expected, $this->newObj()->getValidNamespaces() );
|
||
}
|
||
|
||
public function provideGetValidNamespaces_misc() {
|
||
return [
|
||
'Out of order (T109137)' => [ [ 1, 0 ], [ 0, 1 ] ],
|
||
'Alphabetical order' => [ [ 10, 2 ], [ 2, 10 ] ],
|
||
'Negative' => [ [ -1000, -500, -2, 0 ], [ 0 ] ],
|
||
];
|
||
}
|
||
|
||
// %} End miscellaneous
|
||
// %} End canonical namespaces
|
||
|
||
/**********************************************************************************************
|
||
* Restriction levels
|
||
* %{
|
||
*/
|
||
|
||
/**
|
||
* This mock user can only have isAllowed() called on it.
|
||
*
|
||
* @param array $groups Groups for the mock user to have
|
||
* @return User
|
||
*/
|
||
private function getMockUser( array $groups = [] ) : User {
|
||
$groups[] = '*';
|
||
|
||
$mock = $this->createMock( User::class );
|
||
$mock->method( 'isAllowed' )->will( $this->returnCallback(
|
||
function ( $action ) use ( $groups ) {
|
||
global $wgGroupPermissions, $wgRevokePermissions;
|
||
if ( $action == '' ) {
|
||
return true;
|
||
}
|
||
foreach ( $wgRevokePermissions as $group => $rights ) {
|
||
if ( !in_array( $group, $groups ) ) {
|
||
continue;
|
||
}
|
||
if ( isset( $rights[$action] ) && $rights[$action] ) {
|
||
return false;
|
||
}
|
||
}
|
||
foreach ( $wgGroupPermissions as $group => $rights ) {
|
||
if ( !in_array( $group, $groups ) ) {
|
||
continue;
|
||
}
|
||
if ( isset( $rights[$action] ) && $rights[$action] ) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
) );
|
||
$mock->expects( $this->never() )->method( $this->anythingBut( 'isAllowed' ) );
|
||
return $mock;
|
||
}
|
||
|
||
/**
|
||
* @dataProvider provideGetRestrictionLevels
|
||
* @covers NamespaceInfo::getRestrictionLevels
|
||
*
|
||
* @param array $expected
|
||
* @param int $ns
|
||
* @param User|null $user
|
||
*/
|
||
public function testGetRestrictionLevels( array $expected, $ns, User $user = null ) {
|
||
$this->setMwGlobals( [
|
||
'wgGroupPermissions' => [
|
||
'*' => [ 'edit' => true ],
|
||
'autoconfirmed' => [ 'editsemiprotected' => true ],
|
||
'sysop' => [
|
||
'editsemiprotected' => true,
|
||
'editprotected' => true,
|
||
],
|
||
'privileged' => [ 'privileged' => true ],
|
||
],
|
||
'wgRevokePermissions' => [
|
||
'noeditsemiprotected' => [ 'editsemiprotected' => true ],
|
||
],
|
||
] );
|
||
$obj = $this->newObj( [
|
||
'NamespaceProtection' => [
|
||
NS_MAIN => 'autoconfirmed',
|
||
NS_USER => 'sysop',
|
||
101 => [ 'editsemiprotected', 'privileged' ],
|
||
],
|
||
] );
|
||
$this->assertSame( $expected, $obj->getRestrictionLevels( $ns, $user ) );
|
||
}
|
||
|
||
public function provideGetRestrictionLevels() {
|
||
return [
|
||
'No namespace restriction' => [ [ '', 'autoconfirmed', 'sysop' ], NS_TALK ],
|
||
'Restricted to autoconfirmed' => [ [ '', 'sysop' ], NS_MAIN ],
|
||
'Restricted to sysop' => [ [ '' ], NS_USER ],
|
||
// @todo Bug -- 'sysop' protection should be allowed in this case. Someone who's
|
||
// autoconfirmed and also privileged can edit this namespace, and would be blocked by
|
||
// the sysop protection.
|
||
'Restricted to someone in two groups' => [ [ '' ], 101 ],
|
||
|
||
'No special permissions' => [ [ '' ], NS_TALK, $this->getMockUser() ],
|
||
'autoconfirmed' => [
|
||
[ '', 'autoconfirmed' ],
|
||
NS_TALK,
|
||
$this->getMockUser( [ 'autoconfirmed' ] )
|
||
],
|
||
'autoconfirmed revoked' => [
|
||
[ '' ],
|
||
NS_TALK,
|
||
$this->getMockUser( [ 'autoconfirmed', 'noeditsemiprotected' ] )
|
||
],
|
||
'sysop' => [
|
||
[ '', 'autoconfirmed', 'sysop' ],
|
||
NS_TALK,
|
||
$this->getMockUser( [ 'sysop' ] )
|
||
],
|
||
'sysop with autoconfirmed revoked (a bit silly)' => [
|
||
[ '', 'sysop' ],
|
||
NS_TALK,
|
||
$this->getMockUser( [ 'sysop', 'noeditsemiprotected' ] )
|
||
],
|
||
];
|
||
}
|
||
|
||
// %} End restriction levels
|
||
}
|
||
|
||
/**
|
||
* For really cool vim folding this needs to be at the end:
|
||
* vim: foldmarker=%{,%} foldmethod=marker
|
||
*/
|