Create a CompositeBlock class which extends AbstractBlock and adds the property $originalBlocks. This is for situations where more than one block applies to a user/IP, and avoids the need to choose just one of these blocks to enforce. Behaviour of the resulting block is determined by combining the strictest parameters of the original blocks. Also add DatabaseBlock::newListFromTarget, which is similar to DatabaseBlock::newFromTarget, but returns all relevant blocks, rather than choosing the most specific one. For tracking a CompositeBlock with a cookie, examine the original blocks and only track the first trackable block that is found. Bug: T206163 Change-Id: I088401105ac8ceb2c6117c6d2fcdb277c754d882
254 lines
5.7 KiB
PHP
254 lines
5.7 KiB
PHP
<?php
|
|
|
|
use MediaWiki\Block\BlockRestrictionStore;
|
|
use MediaWiki\Block\CompositeBlock;
|
|
use MediaWiki\Block\Restriction\PageRestriction;
|
|
use MediaWiki\Block\Restriction\NamespaceRestriction;
|
|
use MediaWiki\Block\SystemBlock;
|
|
use MediaWiki\MediaWikiServices;
|
|
|
|
/**
|
|
* @group Database
|
|
* @group Blocking
|
|
* @coversDefaultClass \MediaWiki\Block\CompositeBlock
|
|
*/
|
|
class CompositeBlockTest extends MediaWikiLangTestCase {
|
|
private function getPartialBlocks() {
|
|
$sysopId = $this->getTestSysop()->getUser()->getId();
|
|
|
|
$userBlock = new Block( [
|
|
'address' => $this->getTestUser()->getUser(),
|
|
'by' => $sysopId,
|
|
'sitewide' => false,
|
|
] );
|
|
$ipBlock = new Block( [
|
|
'address' => '127.0.0.1',
|
|
'by' => $sysopId,
|
|
'sitewide' => false,
|
|
] );
|
|
|
|
$userBlock->insert();
|
|
$ipBlock->insert();
|
|
|
|
return [
|
|
'user' => $userBlock,
|
|
'ip' => $ipBlock,
|
|
];
|
|
}
|
|
|
|
private function deleteBlocks( $blocks ) {
|
|
foreach ( $blocks as $block ) {
|
|
$block->delete();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @covers ::__construct
|
|
* @dataProvider provideTestStrictestParametersApplied
|
|
*/
|
|
public function testStrictestParametersApplied( $blocks, $expected ) {
|
|
$this->setMwGlobals( [
|
|
'wgBlockDisablesLogin' => false,
|
|
'wgBlockAllowsUTEdit' => true,
|
|
] );
|
|
|
|
$block = new CompositeBlock( [
|
|
'originalBlocks' => $blocks,
|
|
] );
|
|
|
|
$this->assertSame( $expected[ 'hideName' ], $block->getHideName() );
|
|
$this->assertSame( $expected[ 'sitewide' ], $block->isSitewide() );
|
|
$this->assertSame( $expected[ 'blockEmail' ], $block->isEmailBlocked() );
|
|
$this->assertSame( $expected[ 'allowUsertalk' ], $block->isUsertalkEditAllowed() );
|
|
}
|
|
|
|
public static function provideTestStrictestParametersApplied() {
|
|
return [
|
|
'Sitewide block and partial block' => [
|
|
[
|
|
new Block( [
|
|
'sitewide' => false,
|
|
'blockEmail' => true,
|
|
'allowUsertalk' => true,
|
|
] ),
|
|
new Block( [
|
|
'sitewide' => true,
|
|
'blockEmail' => false,
|
|
'allowUsertalk' => false,
|
|
] ),
|
|
],
|
|
[
|
|
'hideName' => false,
|
|
'sitewide' => true,
|
|
'blockEmail' => true,
|
|
'allowUsertalk' => false,
|
|
],
|
|
],
|
|
'Partial block and system block' => [
|
|
[
|
|
new Block( [
|
|
'sitewide' => false,
|
|
'blockEmail' => true,
|
|
'allowUsertalk' => false,
|
|
] ),
|
|
new SystemBlock( [
|
|
'systemBlock' => 'proxy',
|
|
] ),
|
|
],
|
|
[
|
|
'hideName' => false,
|
|
'sitewide' => true,
|
|
'blockEmail' => true,
|
|
'allowUsertalk' => false,
|
|
],
|
|
],
|
|
'System block and user name hiding block' => [
|
|
[
|
|
new Block( [
|
|
'hideName' => true,
|
|
'sitewide' => true,
|
|
'blockEmail' => true,
|
|
'allowUsertalk' => false,
|
|
] ),
|
|
new SystemBlock( [
|
|
'systemBlock' => 'proxy',
|
|
] ),
|
|
],
|
|
[
|
|
'hideName' => true,
|
|
'sitewide' => true,
|
|
'blockEmail' => true,
|
|
'allowUsertalk' => false,
|
|
],
|
|
],
|
|
'Two lenient partial blocks' => [
|
|
[
|
|
new Block( [
|
|
'sitewide' => false,
|
|
'blockEmail' => false,
|
|
'allowUsertalk' => true,
|
|
] ),
|
|
new Block( [
|
|
'sitewide' => false,
|
|
'blockEmail' => false,
|
|
'allowUsertalk' => true,
|
|
] ),
|
|
],
|
|
[
|
|
'hideName' => false,
|
|
'sitewide' => false,
|
|
'blockEmail' => false,
|
|
'allowUsertalk' => true,
|
|
],
|
|
],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @covers ::appliesToTitle
|
|
*/
|
|
public function testBlockAppliesToTitle() {
|
|
$this->setMwGlobals( [
|
|
'wgBlockDisablesLogin' => false,
|
|
] );
|
|
|
|
$blocks = $this->getPartialBlocks();
|
|
|
|
$block = new CompositeBlock( [
|
|
'originalBlocks' => $blocks,
|
|
] );
|
|
|
|
$pageFoo = $this->getExistingTestPage( 'Foo' );
|
|
$pageBar = $this->getExistingTestPage( 'User:Bar' );
|
|
|
|
$this->getBlockRestrictionStore()->insert( [
|
|
new PageRestriction( $blocks[ 'user' ]->getId(), $pageFoo->getId() ),
|
|
new NamespaceRestriction( $blocks[ 'ip' ]->getId(), NS_USER ),
|
|
] );
|
|
|
|
$this->assertTrue( $block->appliesToTitle( $pageFoo->getTitle() ) );
|
|
$this->assertTrue( $block->appliesToTitle( $pageBar->getTitle() ) );
|
|
|
|
$this->deleteBlocks( $blocks );
|
|
}
|
|
|
|
/**
|
|
* @covers ::appliesToUsertalk
|
|
* @covers ::appliesToPage
|
|
* @covers ::appliesToNamespace
|
|
*/
|
|
public function testBlockAppliesToUsertalk() {
|
|
$this->setMwGlobals( [
|
|
'wgBlockAllowsUTEdit' => true,
|
|
'wgBlockDisablesLogin' => false,
|
|
] );
|
|
|
|
$blocks = $this->getPartialBlocks();
|
|
|
|
$block = new CompositeBlock( [
|
|
'originalBlocks' => $blocks,
|
|
] );
|
|
|
|
$title = $blocks[ 'user' ]->getTarget()->getTalkPage();
|
|
$page = $this->getExistingTestPage( 'User talk:' . $title->getText() );
|
|
|
|
$this->getBlockRestrictionStore()->insert( [
|
|
new PageRestriction( $blocks[ 'user' ]->getId(), $page->getId() ),
|
|
new NamespaceRestriction( $blocks[ 'ip' ]->getId(), NS_USER ),
|
|
] );
|
|
|
|
$this->assertTrue( $block->appliesToUsertalk( $blocks[ 'user' ]->getTarget()->getTalkPage() ) );
|
|
|
|
$this->deleteBlocks( $blocks );
|
|
}
|
|
|
|
/**
|
|
* @covers ::appliesToRight
|
|
* @dataProvider provideTestBlockAppliesToRight
|
|
*/
|
|
public function testBlockAppliesToRight( $blocks, $right, $expected ) {
|
|
$this->setMwGlobals( [
|
|
'wgBlockDisablesLogin' => false,
|
|
] );
|
|
|
|
$block = new CompositeBlock( [
|
|
'originalBlocks' => $blocks,
|
|
] );
|
|
|
|
$this->assertSame( $block->appliesToRight( $right ), $expected );
|
|
}
|
|
|
|
public static function provideTestBlockAppliesToRight() {
|
|
return [
|
|
'Read is not blocked' => [
|
|
[
|
|
new Block(),
|
|
new Block(),
|
|
],
|
|
'read',
|
|
false,
|
|
],
|
|
'Email is blocked if blocked by any blocks' => [
|
|
[
|
|
new Block( [
|
|
'blockEmail' => true,
|
|
] ),
|
|
new Block( [
|
|
'blockEmail' => false,
|
|
] ),
|
|
],
|
|
'sendemail',
|
|
true,
|
|
],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Get an instance of BlockRestrictionStore
|
|
*
|
|
* @return BlockRestrictionStore
|
|
*/
|
|
protected function getBlockRestrictionStore() : BlockRestrictionStore {
|
|
return MediaWikiServices::getInstance()->getBlockRestrictionStore();
|
|
}
|
|
}
|