Viewing File: /home/omtekel/www/wp-content/upgrade/backup/Consequences.tar
ConsequencesLookupTest.php 0000666 00000001700 15133501472 0011745 0 ustar 00 <?php
namespace MediaWiki\Extension\AbuseFilter\Tests\Unit\Consequences;
use MediaWiki\Extension\AbuseFilter\CentralDBManager;
use MediaWiki\Extension\AbuseFilter\Consequences\ConsequencesLookup;
use MediaWiki\Extension\AbuseFilter\Consequences\ConsequencesRegistry;
use MediaWikiUnitTestCase;
use Psr\Log\NullLogger;
use Wikimedia\Rdbms\LBFactory;
/**
* @group Test
* @group AbuseFilter
* @coversDefaultClass \MediaWiki\Extension\AbuseFilter\Consequences\ConsequencesLookup
* @todo Write unit tests (non-trivial because the class is tied to a DB)
*/
class ConsequencesLookupTest extends MediaWikiUnitTestCase {
/**
* @covers ::__construct
*/
public function testConstructor() {
$this->assertInstanceOf(
ConsequencesLookup::class,
new ConsequencesLookup(
$this->createMock( LBFactory::class ),
$this->createMock( CentralDBManager::class ),
$this->createMock( ConsequencesRegistry::class ),
new NullLogger()
)
);
}
}
ConsequencesRegistryTest.php 0000666 00000011163 15133501472 0012310 0 ustar 00 <?php
namespace MediaWiki\Extension\AbuseFilter\Tests\Unit\Consequences;
use MediaWiki\Extension\AbuseFilter\Consequences\Consequence\Consequence;
use MediaWiki\Extension\AbuseFilter\Consequences\ConsequencesRegistry;
use MediaWiki\Extension\AbuseFilter\Hooks\AbuseFilterHookRunner;
use MediaWikiUnitTestCase;
use ReflectionClass;
use RuntimeException;
/**
* @group Test
* @group AbuseFilter
* @coversDefaultClass \MediaWiki\Extension\AbuseFilter\Consequences\ConsequencesRegistry
*/
class ConsequencesRegistryTest extends MediaWikiUnitTestCase {
/**
* @covers ::__construct
*/
public function testConstruct() {
$hookRunner = $this->createMock( AbuseFilterHookRunner::class );
$this->assertInstanceOf(
ConsequencesRegistry::class,
new ConsequencesRegistry( $hookRunner, [] )
);
}
/**
* @covers ::getAllActionNames
*/
public function testGetAllActionNames() {
$configActions = [ 'nothing' => false, 'rickroll' => true ];
$customActionName = 'spell';
$hookRunner = $this->createMock( AbuseFilterHookRunner::class );
$hookRunner->method( 'onAbuseFilterCustomActions' )->willReturnCallback(
static function ( &$actions ) use ( $customActionName ) {
$actions[$customActionName] = 'strlen';
}
);
$expected = [ 'nothing', 'rickroll', 'spell' ];
$registry = new ConsequencesRegistry( $hookRunner, $configActions );
$this->assertSame( $expected, $registry->getAllActionNames() );
}
/**
* @covers ::getAllEnabledActionNames
*/
public function testGetAllEnabledActionNames() {
$configActions = [ 'nothing' => false, 'rickroll' => true ];
$customActionName = 'spell';
$hookRunner = $this->createMock( AbuseFilterHookRunner::class );
$hookRunner->method( 'onAbuseFilterCustomActions' )->willReturnCallback(
static function ( &$actions ) use ( $customActionName ) {
$actions[$customActionName] = 'strlen';
}
);
$expected = [ 'rickroll', 'spell' ];
$registry = new ConsequencesRegistry( $hookRunner, $configActions );
$this->assertSame( $expected, $registry->getAllEnabledActionNames() );
}
/**
* @covers ::getDangerousActionNames
*/
public function testGetDangerousActionNames() {
// Cheat a bit
$regReflection = new ReflectionClass( ConsequencesRegistry::class );
$expected = $regReflection->getConstant( 'DANGEROUS_ACTIONS' );
$registry = new ConsequencesRegistry( $this->createMock( AbuseFilterHookRunner::class ), [] );
$this->assertSame( $expected, $registry->getDangerousActionNames() );
}
/**
* @covers ::getDangerousActionNames
*/
public function testGetDangerousActionNames_hook() {
$extraDangerous = 'rickroll';
$hookRunner = $this->createMock( AbuseFilterHookRunner::class );
$hookRunner->method( 'onAbuseFilterGetDangerousActions' )->willReturnCallback(
static function ( &$array ) use ( $extraDangerous ) {
$array[] = $extraDangerous;
}
);
$registry = new ConsequencesRegistry( $hookRunner, [] );
$this->assertContains( $extraDangerous, $registry->getDangerousActionNames() );
}
/**
* @covers ::getCustomActions
* @covers ::validateCustomActions
*/
public function testGetCustomActions() {
$customActionName = 'rickroll';
$customAction = 'strlen';
$hookRunner = $this->createMock( AbuseFilterHookRunner::class );
$hookRunner->method( 'onAbuseFilterCustomActions' )->willReturnCallback(
static function ( &$actions ) use ( $customActionName, $customAction ) {
$actions[$customActionName] = $customAction;
}
);
$registry = new ConsequencesRegistry( $hookRunner, [] );
$this->assertSame( [ $customActionName => $customAction ], $registry->getCustomActions() );
}
/**
* @covers ::getCustomActions
* @covers ::validateCustomActions
*/
public function testGetCustomActions_invalidKey() {
$hookRunner = $this->createMock( AbuseFilterHookRunner::class );
$hookRunner->method( 'onAbuseFilterCustomActions' )->willReturnCallback(
function ( &$actions ) {
$invalidKey = 42;
$actions[$invalidKey] = $this->createMock( Consequence::class );
}
);
$registry = new ConsequencesRegistry( $hookRunner, [] );
$this->expectException( RuntimeException::class );
$registry->getCustomActions();
}
/**
* @covers ::getCustomActions
* @covers ::validateCustomActions
*/
public function testGetCustomActions_invalidValue() {
$hookRunner = $this->createMock( AbuseFilterHookRunner::class );
$hookRunner->method( 'onAbuseFilterCustomActions' )->willReturnCallback(
static function ( &$actions ) {
$invalidValue = 42;
$actions['myaction'] = $invalidValue;
}
);
$registry = new ConsequencesRegistry( $hookRunner, [] );
$this->expectException( RuntimeException::class );
$registry->getCustomActions();
}
}
Consequence/DisallowTest.php 0000666 00000001703 15133501472 0012151 0 ustar 00 <?php
namespace MediaWiki\Extension\AbuseFilter\Tests\Unit\Consequences\Consequence;
use ConsequenceGetMessageTestTrait;
use MediaWiki\Extension\AbuseFilter\Consequences\Consequence\Disallow;
use MediaWiki\Extension\AbuseFilter\Consequences\Parameters;
use MediaWikiUnitTestCase;
/**
* @coversDefaultClass \MediaWiki\Extension\AbuseFilter\Consequences\Consequence\Disallow
* @covers ::__construct
*/
class DisallowTest extends MediaWikiUnitTestCase {
use ConsequenceGetMessageTestTrait;
/**
* @covers ::execute
*/
public function testExecute() {
$disallow = new Disallow( $this->createMock( Parameters::class ), '' );
$this->assertTrue( $disallow->execute() );
}
/**
* @covers ::getMessage
* @dataProvider provideGetMessageParameters
*/
public function testGetMessage( Parameters $params ) {
$msg = 'some-disallow-message';
$rangeBlock = new Disallow( $params, $msg );
$this->doTestGetMessage( $rangeBlock, $params, $msg );
}
}
Consequence/BlockTest.php 0000666 00000012342 15133501472 0011426 0 ustar 00 <?php
namespace MediaWiki\Extension\AbuseFilter\Tests\Unit\Consequences\Consequence;
use ConsequenceGetMessageTestTrait;
use MediaWiki\Block\BlockUser;
use MediaWiki\Block\BlockUserFactory;
use MediaWiki\Block\DatabaseBlock;
use MediaWiki\Block\DatabaseBlockStore;
use MediaWiki\Extension\AbuseFilter\Consequences\Consequence\Block;
use MediaWiki\Extension\AbuseFilter\Consequences\Parameters;
use MediaWiki\Extension\AbuseFilter\FilterUser;
use MediaWiki\User\UserIdentity;
use MediaWiki\User\UserIdentityValue;
use MediaWikiUnitTestCase;
use MessageLocalizer;
use Psr\Log\NullLogger;
use Status;
/**
* @coversDefaultClass \MediaWiki\Extension\AbuseFilter\Consequences\Consequence\Block
* @covers \MediaWiki\Extension\AbuseFilter\Consequences\Consequence\BlockingConsequence
*/
class BlockTest extends MediaWikiUnitTestCase {
use ConsequenceGetMessageTestTrait;
private function getMsgLocalizer(): MessageLocalizer {
$ml = $this->createMock( MessageLocalizer::class );
$ml->method( 'msg' )->willReturnCallback( function ( $k, $p ) {
return $this->getMockMessage( $k, $p );
} );
return $ml;
}
/**
* This helper is needed because for reverts we check that the blocker is our filter user, so we want
* to always use the same object.
* @return FilterUser
*/
private function getFilterUser(): FilterUser {
$filterUser = $this->createMock( FilterUser::class );
$filterUser->method( 'getUserIdentity' )
->willReturn( new UserIdentityValue( 2, 'FilterUser' ) );
return $filterUser;
}
public static function provideExecute(): iterable {
foreach ( [ true, false ] as $result ) {
$resStr = wfBoolToStr( $result );
yield "IPv4, $resStr" => [ new UserIdentityValue( 0, '1.2.3.4' ), $result ];
yield "IPv6, $resStr" => [
// random IP from https://en.wikipedia.org/w/index.php?title=IPv6&oldid=989727833
new UserIdentityValue( 0, '2001:0db8:0000:0000:0000:ff00:0042:8329' ),
$result
];
yield "Registered, $resStr" => [ new UserIdentityValue( 3, 'Some random user' ), $result ];
}
}
/**
* @dataProvider provideExecute
* @covers ::__construct
* @covers ::execute
*/
public function testExecute( UserIdentity $target, bool $result ) {
$expiry = '1 day';
$params = $this->provideGetMessageParameters( $target )->current()[0];
$blockUser = $this->createMock( BlockUser::class );
$blockUser->expects( $this->once() )
->method( 'placeBlockUnsafe' )
->willReturn( $result ? Status::newGood() : Status::newFatal( 'error' ) );
$blockUserFactory = $this->createMock( BlockUserFactory::class );
$blockUserFactory->expects( $this->once() )
->method( 'newBlockUser' )
->with(
$target->getName(),
$this->anything(),
$expiry,
$this->anything(),
$this->anything()
)
->willReturn( $blockUser );
$block = new Block(
$params,
$expiry,
$preventsTalkEdit = true,
$blockUserFactory,
$this->createMock( DatabaseBlockStore::class ),
static function () {
return null;
},
$this->getFilterUser(),
$this->getMsgLocalizer(),
new NullLogger()
);
$this->assertSame( $result, $block->execute() );
}
/**
* @covers ::getMessage
* @dataProvider provideGetMessageParameters
*/
public function testGetMessage( Parameters $params ) {
$block = new Block(
$params,
'0',
false,
$this->createMock( BlockUserFactory::class ),
$this->createMock( DatabaseBlockStore::class ),
static function () {
return null;
},
$this->createMock( FilterUser::class ),
$this->getMsgLocalizer(),
new NullLogger()
);
$this->doTestGetMessage( $block, $params, 'abusefilter-blocked-display' );
}
public function provideRevert() {
yield 'no block to revert' => [ null, null, false ];
$filterUserIdentity = $this->getFilterUser()->getUserIdentity();
$notAFBlock = $this->createMock( DatabaseBlock::class );
$notAFBlock->method( 'getBy' )->willReturn( $filterUserIdentity->getId() + 1 );
yield 'not blocked by AF user' => [ $notAFBlock, null, false ];
$blockByFilter = $this->createMock( DatabaseBlock::class );
$blockByFilter->method( 'getBy' )->willReturn( $filterUserIdentity->getId() );
$failBlockStore = $this->createMock( DatabaseBlockStore::class );
$failBlockStore->expects( $this->once() )->method( 'deleteBlock' )->willReturn( false );
yield 'cannot delete block' => [ $blockByFilter, $failBlockStore, false ];
$succeedBlockStore = $this->createMock( DatabaseBlockStore::class );
$succeedBlockStore->expects( $this->once() )->method( 'deleteBlock' )->willReturn( true );
yield 'succeed' => [ $blockByFilter, $succeedBlockStore, true ];
}
/**
* @covers ::revert
* @dataProvider provideRevert
*/
public function testRevert( ?DatabaseBlock $block, ?DatabaseBlockStore $blockStore, bool $expected ) {
$params = $this->createMock( Parameters::class );
$params->method( 'getUser' )->willReturn( new UserIdentityValue( 1, 'Foobar' ) );
$block = new Block(
$params,
'0',
false,
$this->createMock( BlockUserFactory::class ),
$blockStore ?? $this->createMock( DatabaseBlockStore::class ),
static function () use ( $block ) {
return $block;
},
$this->getFilterUser(),
$this->getMsgLocalizer(),
new NullLogger()
);
$this->assertSame( $expected, $block->revert( $this->createMock( UserIdentity::class ), '' ) );
}
}
Consequence/BlockAutopromoteTest.php 0000666 00000007376 15133501472 0013700 0 ustar 00 <?php
namespace MediaWiki\Extension\AbuseFilter\Tests\Unit\Consequences\Consequence;
use ConsequenceGetMessageTestTrait;
use MediaWiki\Extension\AbuseFilter\BlockAutopromoteStore;
use MediaWiki\Extension\AbuseFilter\Consequences\Consequence\BlockAutopromote;
use MediaWiki\Extension\AbuseFilter\Consequences\Parameters;
use MediaWiki\User\UserIdentityUtils;
use MediaWiki\User\UserIdentityValue;
use MediaWikiUnitTestCase;
use MessageLocalizer;
/**
* @coversDefaultClass \MediaWiki\Extension\AbuseFilter\Consequences\Consequence\BlockAutopromote
* @covers ::__construct
*/
class BlockAutopromoteTest extends MediaWikiUnitTestCase {
use ConsequenceGetMessageTestTrait;
private function getMsgLocalizer(): MessageLocalizer {
$ml = $this->createMock( MessageLocalizer::class );
$ml->method( 'msg' )->willReturnCallback( function ( $k, $p ) {
return $this->getMockMessage( $k, $p );
} );
return $ml;
}
/**
* @covers ::execute
*/
public function testExecute_anonymous() {
$user = new UserIdentityValue( 0, 'Anonymous user' );
$params = $this->provideGetMessageParameters( $user )->current()[0];
$blockAutopromoteStore = $this->createMock( BlockAutopromoteStore::class );
$blockAutopromoteStore->expects( $this->never() )
->method( 'blockAutoPromote' );
$userIdentityUtils = $this->createMock( UserIdentityUtils::class );
$blockAutopromote = new BlockAutopromote(
$params,
5 * 86400,
$blockAutopromoteStore,
$this->getMsgLocalizer(),
$userIdentityUtils
);
$this->assertFalse( $blockAutopromote->execute() );
}
/**
* @covers ::execute
* @dataProvider provideExecute
*/
public function testExecute( bool $success ) {
$target = new UserIdentityValue( 1, 'A new user' );
$userIdentityUtils = $this->createMock( UserIdentityUtils::class );
$userIdentityUtils->method( 'isNamed' )->willReturn( true );
$params = $this->provideGetMessageParameters( $target )->current()[0];
$duration = 5 * 86400;
$blockAutopromoteStore = $this->createMock( BlockAutopromoteStore::class );
$blockAutopromoteStore->expects( $this->once() )
->method( 'blockAutoPromote' )
->with( $target, $this->anything(), $duration )
->willReturn( $success );
$blockAutopromote = new BlockAutopromote(
$params,
$duration,
$blockAutopromoteStore,
$this->getMsgLocalizer(),
$userIdentityUtils
);
$this->assertSame( $success, $blockAutopromote->execute() );
}
public static function provideExecute(): array {
return [
[ true ],
[ false ]
];
}
/**
* @covers ::revert
* @dataProvider provideExecute
*/
public function testRevert( bool $success ) {
$target = new UserIdentityValue( 1, 'A new user' );
$performer = new UserIdentityValue( 2, 'Reverting user' );
$params = $this->provideGetMessageParameters( $target )->current()[0];
$blockAutopromoteStore = $this->createMock( BlockAutopromoteStore::class );
$blockAutopromoteStore->expects( $this->once() )
->method( 'unblockAutoPromote' )
->with( $target, $performer, $this->anything() )
->willReturn( $success );
$userIdentityUtils = $this->createMock( UserIdentityUtils::class );
$blockAutopromote = new BlockAutopromote(
$params,
0,
$blockAutopromoteStore,
$this->getMsgLocalizer(),
$userIdentityUtils
);
$this->assertSame( $success, $blockAutopromote->revert( $performer, 'reason' ) );
}
/**
* @covers ::getMessage
* @dataProvider provideGetMessageParameters
*/
public function testGetMessage( Parameters $params ) {
$userIdentityUtils = $this->createMock( UserIdentityUtils::class );
$rangeBlock = new BlockAutopromote(
$params,
83,
$this->createMock( BlockAutopromoteStore::class ),
$this->getMsgLocalizer(),
$userIdentityUtils
);
$this->doTestGetMessage( $rangeBlock, $params, 'abusefilter-autopromote-blocked' );
}
}
Consequence/ThrottleTest.php 0000666 00000014255 15133501473 0012207 0 ustar 00 <?php
namespace MediaWiki\Extension\AbuseFilter\Tests\Unit\Consequences\Consequence;
use BagOStuff;
use Generator;
use HashBagOStuff;
use InvalidArgumentException;
use MediaWiki\Extension\AbuseFilter\ActionSpecifier;
use MediaWiki\Extension\AbuseFilter\Consequences\Consequence\Throttle;
use MediaWiki\Extension\AbuseFilter\Consequences\ConsequenceNotPrecheckedException;
use MediaWiki\Extension\AbuseFilter\Consequences\Parameters;
use MediaWiki\Extension\AbuseFilter\Filter\ExistingFilter;
use MediaWiki\Linker\LinkTarget;
use MediaWiki\Title\Title;
use MediaWiki\User\UserEditTracker;
use MediaWiki\User\UserFactory;
use MediaWiki\User\UserIdentity;
use MediaWiki\User\UserIdentityValue;
use MediaWikiUnitTestCase;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\NullLogger;
use Wikimedia\TestingAccessWrapper;
/**
* @coversDefaultClass \MediaWiki\Extension\AbuseFilter\Consequences\Consequence\Throttle
* @covers ::__construct
*/
class ThrottleTest extends MediaWikiUnitTestCase {
private function getThrottle(
array $throttleParams = [],
BagOStuff $cache = null,
bool $globalFilter = false,
UserIdentity $user = null,
Title $title = null,
UserEditTracker $editTracker = null,
string $ip = null
) {
$specifier = new ActionSpecifier(
'some-action',
$title ?? $this->createMock( LinkTarget::class ),
$user ?? $this->createMock( UserIdentity::class ),
$ip ?? '1.2.3.4',
null
);
$params = new Parameters(
$this->createMock( ExistingFilter::class ),
$globalFilter,
$specifier
);
return new Throttle(
$params,
$throttleParams + [ 'groups' => [ 'user' ], 'count' => 3, 'period' => 60, 'id' => 1 ],
$cache ?? new HashBagOStuff(),
$editTracker ?? $this->createMock( UserEditTracker::class ),
$this->createMock( UserFactory::class ),
new NullLogger(),
false,
$globalFilter ? 'foo-db' : null
);
}
/**
* @covers ::execute
*/
public function testExecute_notPrechecked() {
$throttle = $this->getThrottle();
$this->expectException( ConsequenceNotPrecheckedException::class );
$throttle->execute();
}
public function provideThrottle() {
foreach ( [ false, true ] as $global ) {
$globalStr = $global ? 'global' : 'local';
yield "no groups, $globalStr" => [ $this->getThrottle( [ 'groups' => [] ], null, $global ), true ];
$cache = $this->getMockBuilder( HashBagOStuff::class )->onlyMethods( [ 'incrWithInit' ] )->getMock();
yield "no cache value set, $globalStr" => [ $this->getThrottle( [], $cache, $global ), true, $cache ];
$groups = [ 'ip', 'user', 'range', 'creationdate', 'editcount', 'site', 'page' ];
foreach ( $groups as $group ) {
$throttle = $this->getThrottle( [ 'groups' => [ $group ], 'count' => 0 ], null, $global );
/** @var Throttle $throttleWr */
$throttleWr = TestingAccessWrapper::newFromObject( $throttle );
$throttleWr->setThrottled( $group );
yield "$group set, $globalStr" => [ $throttle, false ];
}
}
}
/**
* @covers ::shouldDisableOtherConsequences
* @covers ::isThrottled
* @covers ::throttleKey
* @covers ::throttleIdentifier
* @dataProvider provideThrottle
*/
public function testShouldDisableOtherConsequences( Throttle $throttle, bool $shouldDisable ) {
$this->assertSame( $shouldDisable, $throttle->shouldDisableOtherConsequences() );
}
/**
* @covers ::execute
* @covers ::setThrottled
* @covers ::throttleKey
* @covers ::throttleIdentifier
* @dataProvider provideThrottle
*/
public function testExecute( Throttle $throttle, bool $shouldDisable, MockObject $cache = null ) {
if ( $cache ) {
/** @var Throttle $wrapper */
$wrapper = TestingAccessWrapper::newFromObject( $throttle );
$groupCount = count( $wrapper->throttleParams['groups'] );
$cache->expects( $this->exactly( $groupCount ) )->method( 'incrWithInit' );
}
$throttle->shouldDisableOtherConsequences();
$this->assertSame( $shouldDisable, $throttle->execute() );
}
/**
* @covers ::throttleIdentifier
* @dataProvider provideThrottleDataForIdentifiers
*/
public function testThrottleIdentifier(
string $type,
?string $expected,
string $ip,
Title $title,
UserIdentity $user,
UserEditTracker $editTracker = null
) {
$throttle = $this->getThrottle( [], null, false, $user, $title, $editTracker, $ip );
/** @var Throttle $throttleWrapper */
$throttleWrapper = TestingAccessWrapper::newFromObject( $throttle );
if ( $expected === null ) {
$this->expectException( InvalidArgumentException::class );
}
$this->assertSame( $expected, $throttleWrapper->throttleIdentifier( $type ) );
}
public function provideThrottleDataForIdentifiers(): Generator {
$pageName = 'AbuseFilter test throttle identifiers';
$title = $this->createMock( Title::class );
$title->method( 'getPrefixedText' )->willReturn( $pageName );
$ip = '42.42.42.42';
$anon = new UserIdentityValue( 0, $ip );
yield 'IP, simple' => [ 'ip', "ip-$ip", $ip, $title, $anon ];
yield 'user, anonymous' => [ 'user', 'user-0', $ip, $title, $anon ];
$userID = 123;
$user = new UserIdentityValue( $userID, 'Username' );
yield 'user, registered' => [ 'user', "user-$userID", $ip, $title, $user ];
$editcount = 5;
$uet = $this->createMock( UserEditTracker::class );
$uet->method( 'getUserEditCount' )->with( $user )->willReturn( $editcount );
yield 'editcount, simple' => [ 'editcount', "editcount-$editcount", $ip, $title, $user, $uet ];
yield 'page, simple' => [ 'page', "page-$pageName", $ip, $title, $user ];
yield 'site, simple' => [ 'site', 'site-1', $ip, $title, $user ];
yield 'non-existing throttle type' => [ 'foo', null, $ip, $title, $user ];
$testingIPs = [
'123.123.123.123' => '123.123.0.0/16',
'100.0.0.0' => '100.0.0.0/16',
'255.255.0.0' => '255.255.0.0/16',
'1.2.3.4' => '1.2.0.0/16',
'2001:0db8:0000:0000:0000:0000:1428:57ab' => '2001:DB8:0:0:0:0:0:0/64',
'2001:0db8::1428:57ab' => '2001:DB8:0:0:0:0:0:0/64',
'2001:0dff:ffff:ffff:ffff:ffff:ffff:ffff' => '2001:DFF:FFFF:FFFF:0:0:0:0/64',
'2001:db8::' => '2001:DB8:0:0:0:0:0:0/64',
'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff' => 'FFFF:FFFF:FFFF:FFFF:0:0:0:0/64'
];
foreach ( $testingIPs as $testIP => $expected ) {
yield "range, $testIP" => [ 'range', "range-$expected", $testIP, $title, $user ];
}
}
}
Consequence/BuiltinPrioritiesTest.php 0000666 00000002370 15133501473 0014055 0 ustar 00 <?php
namespace MediaWiki\Extension\AbuseFilter\Tests\Unit\Consequences\Consequence;
use BagOStuff;
use MediaWiki\Extension\AbuseFilter\Consequences\Consequence\Throttle;
use MediaWiki\Extension\AbuseFilter\Consequences\Consequence\Warn;
use MediaWiki\Extension\AbuseFilter\Consequences\Parameters;
use MediaWiki\Session\Session;
use MediaWiki\User\UserEditTracker;
use MediaWiki\User\UserFactory;
use MediaWikiUnitTestCase;
use Psr\Log\NullLogger;
/**
* Test for priorities of builtin ConsequencesDisablerConsequence classes
*/
class BuiltinPrioritiesTest extends MediaWikiUnitTestCase {
/**
* @covers \MediaWiki\Extension\AbuseFilter\Consequences\Consequence\Throttle::getSort
* @covers \MediaWiki\Extension\AbuseFilter\Consequences\Consequence\Warn::getSort
*/
public function testThrottleMoreImportantThanWarn() {
$throttle = new Throttle(
$this->createMock( Parameters::class ),
[],
$this->createMock( BagOStuff::class ),
$this->createMock( UserEditTracker::class ),
$this->createMock( UserFactory::class ),
new NullLogger(),
'',
false
);
$warn = new Warn(
$this->createMock( Parameters::class ),
'',
$this->createMock( Session::class )
);
$this->assertLessThan( $warn->getSort(), $throttle->getSort() );
}
}
Consequence/WarnTest.php 0000666 00000006631 15133501473 0011310 0 ustar 00 <?php
namespace MediaWiki\Extension\AbuseFilter\Tests\Unit\Consequences\Consequence;
use ConsequenceGetMessageTestTrait;
use MediaWiki\Extension\AbuseFilter\ActionSpecifier;
use MediaWiki\Extension\AbuseFilter\Consequences\Consequence\Warn;
use MediaWiki\Extension\AbuseFilter\Consequences\ConsequenceNotPrecheckedException;
use MediaWiki\Extension\AbuseFilter\Consequences\Parameters;
use MediaWiki\Extension\AbuseFilter\Filter\ExistingFilter;
use MediaWiki\Session\Session;
use MediaWiki\User\UserIdentityValue;
use MediaWikiUnitTestCase;
use PHPUnit\Framework\MockObject\MockObject;
use TitleValue;
use Wikimedia\TestingAccessWrapper;
/**
* @coversDefaultClass \MediaWiki\Extension\AbuseFilter\Consequences\Consequence\Warn
* @covers ::__construct
*/
class WarnTest extends MediaWikiUnitTestCase {
use ConsequenceGetMessageTestTrait;
private function getWarn( Parameters $params = null ): Warn {
return new Warn(
$params ?? $this->createMock( Parameters::class ),
'foo-bar-message',
$this->createMock( Session::class )
);
}
private function getParamsAndWarnKey(): array {
$filter = $this->createMock( ExistingFilter::class );
$filter->method( 'getID' )->willReturn( 42 );
$params = new Parameters(
$filter,
false,
new ActionSpecifier(
'edit',
new TitleValue( NS_HELP, 'Some title' ),
new UserIdentityValue( 1, 'Warned user' ),
'1.2.3.4',
null
)
);
/** @var Warn $warnWrap */
$warnWrap = TestingAccessWrapper::newFromObject( $this->getWarn( $params ) );
return [ $params, $warnWrap->getWarnKey() ];
}
/**
* @covers ::execute
*/
public function testExecute_notPrechecked() {
$warn = $this->getWarn();
$this->expectException( ConsequenceNotPrecheckedException::class );
$warn->execute();
}
public function provideWarnsAndSuccess() {
$mockSession = $this->createMock( Session::class );
$noKeyWarn = new Warn(
$this->getParamsAndWarnKey()[0],
'some-msg',
$mockSession
);
yield 'should warn' => [ $noKeyWarn, true, $mockSession ];
[ $params, $key ] = $this->getParamsAndWarnKey();
$keySession = $this->createMock( Session::class );
$keySession->method( 'offsetExists' )->with( $key )->willReturn( true );
$keySession->method( 'offsetGet' )->with( $key )->willReturn( true );
$keyWarn = new Warn(
$params,
'some-msg',
$keySession
);
yield 'already warned' => [ $keyWarn, false, $keySession ];
}
/**
* @covers ::shouldDisableOtherConsequences
* @covers ::shouldBeWarned
* @covers ::getWarnKey
* @dataProvider provideWarnsAndSuccess
*/
public function testShouldDisableOtherConsequences( Warn $warn, bool $shouldDisable ) {
$this->assertSame( $shouldDisable, $warn->shouldDisableOtherConsequences() );
}
/**
* @covers ::execute
* @covers ::setWarn
* @covers ::getWarnKey
* @dataProvider provideWarnsAndSuccess
*/
public function testExecute( Warn $warn, bool $shouldDisable, MockObject $session ) {
$session->expects( $this->once() )
->method( 'offsetSet' )
->with( $this->anything(), $shouldDisable );
$warn->shouldDisableOtherConsequences();
$this->assertSame( $shouldDisable, $warn->execute() );
}
/**
* @covers ::getMessage
* @dataProvider provideGetMessageParameters
*/
public function testGetMessage( Parameters $params ) {
$msg = 'some-warning-message';
$rangeBlock = new Warn( $params, $msg, $this->createMock( Session::class ) );
$this->doTestGetMessage( $rangeBlock, $params, $msg );
}
}
Consequence/RangeBlockTest.php 0000666 00000007157 15133501473 0012414 0 ustar 00 <?php
namespace MediaWiki\Extension\AbuseFilter\Tests\Unit\Consequences\Consequence;
use ConsequenceGetMessageTestTrait;
use MediaWiki\Block\BlockUser;
use MediaWiki\Block\BlockUserFactory;
use MediaWiki\Extension\AbuseFilter\ActionSpecifier;
use MediaWiki\Extension\AbuseFilter\Consequences\Consequence\RangeBlock;
use MediaWiki\Extension\AbuseFilter\Consequences\Parameters;
use MediaWiki\Extension\AbuseFilter\Filter\ExistingFilter;
use MediaWiki\Extension\AbuseFilter\FilterUser;
use MediaWikiUnitTestCase;
use MessageLocalizer;
use Psr\Log\NullLogger;
use Status;
/**
* @coversDefaultClass \MediaWiki\Extension\AbuseFilter\Consequences\Consequence\RangeBlock
* @covers \MediaWiki\Extension\AbuseFilter\Consequences\Consequence\BlockingConsequence
*/
class RangeBlockTest extends MediaWikiUnitTestCase {
use ConsequenceGetMessageTestTrait;
private const CIDR_LIMIT = [
'IPv4' => 16,
'IPv6' => 19,
];
private function getMsgLocalizer(): MessageLocalizer {
$ml = $this->createMock( MessageLocalizer::class );
$ml->method( 'msg' )->willReturnCallback( function ( $k, $p ) {
return $this->getMockMessage( $k, $p );
} );
return $ml;
}
public static function provideExecute(): iterable {
yield 'IPv4 range block' => [
'1.2.3.4',
[
'IPv4' => 16,
'IPv6' => 18,
],
'1.2.0.0/16',
true
];
yield 'IPv6 range block' => [
// random IP from https://en.wikipedia.org/w/index.php?title=IPv6&oldid=989727833
'2001:0db8:0000:0000:0000:ff00:0042:8329',
[
'IPv4' => 15,
'IPv6' => 19,
],
'2001:0:0:0:0:0:0:0/19',
true
];
yield 'IPv4 range block constrained by core limits' => [
'1.2.3.4',
[
'IPv4' => 15,
'IPv6' => 19,
],
'1.2.0.0/16',
true
];
yield 'IPv6 range block constrained by core limits' => [
'2001:0db8:0000:0000:0000:ff00:0042:8329',
[
'IPv4' => 16,
'IPv6' => 18,
],
'2001:0:0:0:0:0:0:0/19',
true
];
yield 'failure' => [
'1.2.3.4',
self::CIDR_LIMIT,
'1.2.0.0/16',
false
];
}
/**
* @dataProvider provideExecute
* @covers ::__construct
* @covers ::execute
*/
public function testExecute(
string $requestIP, array $rangeBlockSize, string $target, bool $result
) {
$specifier = $this->createMock( ActionSpecifier::class );
$specifier->method( 'getIP' )->willReturn( $requestIP );
$params = new Parameters(
$this->createMock( ExistingFilter::class ),
false,
$specifier
);
$blockUser = $this->createMock( BlockUser::class );
$blockUser->expects( $this->once() )
->method( 'placeBlockUnsafe' )
->willReturn( $result ? Status::newGood() : Status::newFatal( 'error' ) );
$blockUserFactory = $this->createMock( BlockUserFactory::class );
$blockUserFactory->expects( $this->once() )
->method( 'newBlockUser' )
->with(
$target,
$this->anything(),
'1 week',
$this->anything(),
$this->anything()
)
->willReturn( $blockUser );
$rangeBlock = new RangeBlock(
$params,
'1 week',
$blockUserFactory,
$this->createMock( FilterUser::class ),
$this->getMsgLocalizer(),
new NullLogger(),
$rangeBlockSize,
self::CIDR_LIMIT
);
$this->assertSame( $result, $rangeBlock->execute() );
}
/**
* @covers ::getMessage
* @dataProvider provideGetMessageParameters
*/
public function testGetMessage( Parameters $params ) {
$rangeBlock = new RangeBlock(
$params,
'0',
$this->createMock( BlockUserFactory::class ),
$this->createMock( FilterUser::class ),
$this->getMsgLocalizer(),
new NullLogger(),
[ 'IPv6' => 24, 'IPv4' => 24 ],
self::CIDR_LIMIT
);
$this->doTestGetMessage( $rangeBlock, $params, 'abusefilter-blocked-display' );
}
}
Consequence/TagTest.php 0000666 00000002152 15133501473 0011106 0 ustar 00 <?php
namespace MediaWiki\Extension\AbuseFilter\Tests\Unit\Consequences\Consequence;
use MediaWiki\Extension\AbuseFilter\ActionSpecifier;
use MediaWiki\Extension\AbuseFilter\ChangeTags\ChangeTagger;
use MediaWiki\Extension\AbuseFilter\Consequences\Consequence\Tag;
use MediaWiki\Extension\AbuseFilter\Consequences\Parameters;
use MediaWikiUnitTestCase;
/**
* @coversDefaultClass \MediaWiki\Extension\AbuseFilter\Consequences\Consequence\Tag
* @covers ::__construct
*/
class TagTest extends MediaWikiUnitTestCase {
/**
* @covers ::execute
*/
public function testExecute() {
$tagsToAdd = [ 'tag1', 'tag2' ];
$specifier = $this->createMock( ActionSpecifier::class );
$params = $this->createMock( Parameters::class );
$params->expects( $this->once() )->method( 'getActionSpecifier' )
->willReturn( $specifier );
$tagger = $this->createMock( ChangeTagger::class );
$tagger->expects( $this->once() )->method( 'addTags' )
->with(
$this->identicalTo( $specifier ),
$this->identicalTo( $tagsToAdd )
);
$tag = new Tag( $params, $tagsToAdd, $tagger );
$this->assertTrue( $tag->execute() );
}
}
ConsequencesExecutorFactoryTest.php 0000666 00000002706 15133501473 0013632 0 ustar 00 <?php
namespace MediaWiki\Extension\AbuseFilter\Tests\Unit\Consequences;
use MediaWiki\Config\ServiceOptions;
use MediaWiki\Extension\AbuseFilter\ActionSpecifier;
use MediaWiki\Extension\AbuseFilter\Consequences\ConsequencesExecutorFactory;
use MediaWiki\Extension\AbuseFilter\Consequences\ConsequencesFactory;
use MediaWiki\Extension\AbuseFilter\Consequences\ConsequencesLookup;
use MediaWiki\Extension\AbuseFilter\Consequences\ConsequencesRegistry;
use MediaWiki\Extension\AbuseFilter\FilterLookup;
use MediaWiki\Extension\AbuseFilter\Variables\VariableHolder;
use MediaWiki\User\UserIdentityUtils;
use MediaWikiUnitTestCase;
use Psr\Log\NullLogger;
/**
* @group Test
* @group AbuseFilter
* @coversDefaultClass \MediaWiki\Extension\AbuseFilter\Consequences\ConsequencesExecutorFactory
*/
class ConsequencesExecutorFactoryTest extends MediaWikiUnitTestCase {
/**
* @covers ::__construct
* @covers ::newExecutor
*/
public function testNewExecutor() {
$factory = new ConsequencesExecutorFactory(
$this->createMock( ConsequencesLookup::class ),
$this->createMock( ConsequencesFactory::class ),
$this->createMock( ConsequencesRegistry::class ),
$this->createMock( FilterLookup::class ),
new NullLogger(),
$this->createMock( UserIdentityUtils::class ),
$this->createMock( ServiceOptions::class )
);
$factory->newExecutor(
$this->createMock( ActionSpecifier::class ),
new VariableHolder()
);
$this->addToAssertionCount( 1 );
}
}
ConsequencesFactoryTest.php 0000666 00000007015 15133501473 0012111 0 ustar 00 <?php
namespace MediaWiki\Extension\AbuseFilter\Tests\Unit\Consequences;
use HashBagOStuff;
use MediaWiki\Block\BlockUserFactory;
use MediaWiki\Block\DatabaseBlockStore;
use MediaWiki\Config\ServiceOptions;
use MediaWiki\Extension\AbuseFilter\BlockAutopromoteStore;
use MediaWiki\Extension\AbuseFilter\ChangeTags\ChangeTagger;
use MediaWiki\Extension\AbuseFilter\Consequences\ConsequencesFactory;
use MediaWiki\Extension\AbuseFilter\Consequences\Parameters;
use MediaWiki\Extension\AbuseFilter\FilterUser;
use MediaWiki\Extension\AbuseFilter\Variables\VariableHolder;
use MediaWiki\Session\Session;
use MediaWiki\User\UserEditTracker;
use MediaWiki\User\UserFactory;
use MediaWiki\User\UserGroupManager;
use MediaWiki\User\UserIdentityUtils;
use MediaWikiUnitTestCase;
use MessageLocalizer;
use Psr\Log\NullLogger;
/**
* @group Test
* @group AbuseFilter
* @coversDefaultClass \MediaWiki\Extension\AbuseFilter\Consequences\ConsequencesFactory
* @covers ::__construct
*/
class ConsequencesFactoryTest extends MediaWikiUnitTestCase {
private function getFactory(): ConsequencesFactory {
$opts = new ServiceOptions(
ConsequencesFactory::CONSTRUCTOR_OPTIONS,
[
'AbuseFilterCentralDB' => false,
'AbuseFilterIsCentral' => false,
'AbuseFilterRangeBlockSize' => [],
'BlockCIDRLimit' => [],
]
);
$consequencesFactory = new ConsequencesFactory(
$opts,
new NullLogger(),
$this->createMock( BlockUserFactory::class ),
$this->createMock( DatabaseBlockStore::class ),
$this->createMock( UserGroupManager::class ),
new HashBagOStuff(),
$this->createMock( ChangeTagger::class ),
$this->createMock( BlockAutopromoteStore::class ),
$this->createMock( FilterUser::class ),
$this->createMock( MessageLocalizer::class ),
$this->createMock( UserEditTracker::class ),
$this->createMock( UserFactory::class ),
$this->createMock( UserIdentityUtils::class )
);
$consequencesFactory->setSession( $this->createMock( Session::class ) );
return $consequencesFactory;
}
/**
* @covers ::newBlock
*/
public function testNewBlock() {
$this->getFactory()->newBlock( $this->createMock( Parameters::class ), '', false );
$this->addToAssertionCount( 1 );
}
/**
* @covers ::newRangeBlock
*/
public function testNewRangeBlock() {
$this->getFactory()->newRangeBlock( $this->createMock( Parameters::class ), '' );
$this->addToAssertionCount( 1 );
}
/**
* @covers ::newDegroup
*/
public function testNewDegroup() {
$this->getFactory()->newDegroup( $this->createMock( Parameters::class ), new VariableHolder() );
$this->addToAssertionCount( 1 );
}
/**
* @covers ::newBlockAutopromote
*/
public function testNewBlockAutopromote() {
$this->getFactory()->newBlockAutopromote( $this->createMock( Parameters::class ), 42 );
$this->addToAssertionCount( 1 );
}
/**
* @covers ::newThrottle
*/
public function testNewThrottle() {
$this->getFactory()->newThrottle( $this->createMock( Parameters::class ), [] );
$this->addToAssertionCount( 1 );
}
/**
* @covers ::newWarn
*/
public function testNewWarn() {
$this->getFactory()->newWarn( $this->createMock( Parameters::class ), '' );
$this->addToAssertionCount( 1 );
}
/**
* @covers ::newDisallow
*/
public function testNewDisallow() {
$this->getFactory()->newDisallow( $this->createMock( Parameters::class ), '' );
$this->addToAssertionCount( 1 );
}
/**
* @covers ::newTag
*/
public function testNewTag() {
$this->getFactory()->newTag( $this->createMock( Parameters::class ), [] );
$this->addToAssertionCount( 1 );
}
}
ParametersTest.php 0000666 00000002734 15133501473 0010234 0 ustar 00 <?php
namespace MediaWiki\Extension\AbuseFilter\Tests\Unit\Consequences;
use MediaWiki\Extension\AbuseFilter\ActionSpecifier;
use MediaWiki\Extension\AbuseFilter\Consequences\Parameters;
use MediaWiki\Extension\AbuseFilter\Filter\ExistingFilter;
use MediaWiki\Linker\LinkTarget;
use MediaWiki\User\UserIdentity;
use MediaWikiUnitTestCase;
/**
* @group Test
* @group AbuseFilter
* @coversDefaultClass \MediaWiki\Extension\AbuseFilter\Consequences\Parameters
*/
class ParametersTest extends MediaWikiUnitTestCase {
/**
* @covers ::__construct
* @covers ::getFilter
* @covers ::getIsGlobalFilter
* @covers ::getActionSpecifier
* @covers ::getUser
* @covers ::getTarget
* @covers ::getAction
*/
public function testGetters() {
$filter = $this->createMock( ExistingFilter::class );
$global = true;
$user = $this->createMock( UserIdentity::class );
$target = $this->createMock( LinkTarget::class );
$action = 'some-action';
$specifier = new ActionSpecifier( $action, $target, $user, '1.2.3.4', null );
$params = new Parameters( $filter, $global, $specifier );
$this->assertSame( $filter, $params->getFilter(), 'filter' );
$this->assertSame( $global, $params->getIsGlobalFilter(), 'global' );
$this->assertSame( $specifier, $params->getActionSpecifier(), 'specifier' );
$this->assertSame( $user, $params->getUser(), 'user' );
$this->assertSame( $target, $params->getTarget(), 'target' );
$this->assertSame( $action, $params->getAction(), 'action' );
}
}
ConsequencesExecutorTest.php 0000666 00000015071 15133501473 0012301 0 ustar 00 <?php
namespace MediaWiki\Extension\AbuseFilter\Tests\Unit\Consequences;
use MediaWiki\Config\ServiceOptions;
use MediaWiki\Extension\AbuseFilter\ActionSpecifier;
use MediaWiki\Extension\AbuseFilter\Consequences\Consequence\Block;
use MediaWiki\Extension\AbuseFilter\Consequences\Consequence\Throttle;
use MediaWiki\Extension\AbuseFilter\Consequences\Consequence\Warn;
use MediaWiki\Extension\AbuseFilter\Consequences\ConsequencesExecutor;
use MediaWiki\Extension\AbuseFilter\Consequences\ConsequencesFactory;
use MediaWiki\Extension\AbuseFilter\Consequences\ConsequencesLookup;
use MediaWiki\Extension\AbuseFilter\Consequences\ConsequencesRegistry;
use MediaWiki\Extension\AbuseFilter\Consequences\Parameters;
use MediaWiki\Extension\AbuseFilter\FilterLookup;
use MediaWiki\Extension\AbuseFilter\Variables\VariableHolder;
use MediaWiki\Linker\LinkTarget;
use MediaWiki\User\UserIdentity;
use MediaWiki\User\UserIdentityUtils;
use MediaWikiUnitTestCase;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\NullLogger;
use Wikimedia\TestingAccessWrapper;
/**
* @group Test
* @group AbuseFilter
* @coversDefaultClass \MediaWiki\Extension\AbuseFilter\Consequences\ConsequencesExecutor
*/
class ConsequencesExecutorTest extends MediaWikiUnitTestCase {
/**
* Returns a ConsequencesFactory where:
* - all the ConsequenceDisablerConsequence's created will disable other consequences.
* - the block expiry is set as normal
* @return ConsequencesFactory|MockObject
*/
private function getConsequencesFactory() {
$consFactory = $this->createMock( ConsequencesFactory::class );
$warn = $this->createMock( Warn::class );
$warn->method( 'shouldDisableOtherConsequences' )->willReturn( true );
$consFactory->method( 'newWarn' )->willReturn( $warn );
$throttle = $this->createMock( Throttle::class );
$throttle->method( 'shouldDisableOtherConsequences' )->willReturn( true );
$consFactory->method( 'newThrottle' )->willReturn( $throttle );
$consFactory->method( 'newBlock' )->willReturnCallback(
function ( Parameters $params, string $expiry, bool $preventsTalk ): Block {
$block = $this->createMock( Block::class );
$block->method( 'getExpiry' )->willReturn( $expiry );
return $block;
}
);
return $consFactory;
}
private function getConsExecutor( array $consequences ): ConsequencesExecutor {
$locallyDisabledActions = [
'flag' => false,
'throttle' => false,
'warn' => false,
'disallow' => false,
'blockautopromote' => true,
'block' => true,
'rangeblock' => true,
'degroup' => true,
'tag' => false
];
$options = new ServiceOptions(
ConsequencesExecutor::CONSTRUCTOR_OPTIONS,
[
'AbuseFilterLocallyDisabledGlobalActions' => $locallyDisabledActions,
'AbuseFilterBlockDuration' => '24 hours',
'AbuseFilterAnonBlockDuration' => '24 hours',
'AbuseFilterBlockAutopromoteDuration' => '5 days',
]
);
$consRegistry = $this->createMock( ConsequencesRegistry::class );
$dangerousActions = TestingAccessWrapper::constant( ConsequencesRegistry::class, 'DANGEROUS_ACTIONS' );
$consRegistry->method( 'getDangerousActionNames' )->willReturn( $dangerousActions );
$consLookup = $this->createMock( ConsequencesLookup::class );
$consLookup->expects( $this->atLeastOnce() )
->method( 'getConsequencesForFilters' )
->with( array_keys( $consequences ) )
->willReturn( $consequences );
return new ConsequencesExecutor(
$consLookup,
$this->getConsequencesFactory(),
$consRegistry,
$this->createMock( FilterLookup::class ),
new NullLogger,
$this->createMock( UserIdentityUtils::class ),
$options,
new ActionSpecifier(
'edit',
$this->createMock( LinkTarget::class ),
$this->createMock( UserIdentity::class ),
'1.2.3.4',
null
),
new VariableHolder
);
}
/**
* @param array $rawConsequences A raw, unfiltered list of consequences
* @param array $expectedKeys
*
* @covers ::getActualConsequencesToExecute
* @covers ::replaceLegacyParameters
* @covers ::specializeParameters
* @covers ::removeForbiddenConsequences
* @covers ::replaceArraysWithConsequences
* @covers ::applyConsequenceDisablers
* @covers ::deduplicateConsequences
* @covers ::removeRedundantConsequences
* @dataProvider provideConsequences
*/
public function testGetActualConsequencesToExecute(
array $rawConsequences,
array $expectedKeys
): void {
$executor = $this->getConsExecutor( $rawConsequences );
$actual = $executor->getActualConsequencesToExecute( array_keys( $rawConsequences ) );
$actualKeys = [];
foreach ( $actual as $filter => $actions ) {
$actualKeys[$filter] = array_keys( $actions );
}
$this->assertEquals( $expectedKeys, $actualKeys );
}
/**
* @return array
*/
public static function provideConsequences(): array {
return [
'warn and throttle exclude other actions' => [
[
2 => [
'warn' => [
'abusefilter-warning'
],
'tag' => [
'some tag'
]
],
13 => [
'throttle' => [
'13',
'14,15',
'user'
],
'disallow' => []
],
168 => [
'degroup' => []
]
],
[
2 => [ 'warn' ],
13 => [ 'throttle' ],
168 => [ 'degroup' ]
],
],
'warn excludes other actions, block excludes disallow' => [
[
3 => [
'tag' => [
'some tag'
]
],
'global-2' => [
'warn' => [
'abusefilter-beautiful-warning'
],
'degroup' => []
],
4 => [
'disallow' => [],
'block' => [
'blocktalk',
'15 minutes',
'indefinite'
]
]
],
[
3 => [ 'tag' ],
'global-2' => [ 'warn' ],
4 => [ 'block' ]
],
],
'some global actions are disabled locally, the longest block is chosen' => [
[
'global-1' => [
'blockautopromote' => [],
'block' => [
'blocktalk',
'indefinite',
'indefinite'
]
],
1 => [
'block' => [
'blocktalk',
'4 hours',
'4 hours'
]
],
2 => [
'degroup' => [],
'block' => [
'blocktalk',
'infinity',
'never'
]
]
],
[
'global-1' => [],
1 => [],
2 => [ 'degroup', 'block' ]
],
],
'do not use a block that will be skipped as the longer one' => [
[
1 => [
'warn' => [
'abusefilter-warning'
],
'block' => [
'blocktalk',
'4 hours',
'4 hours'
]
],
2 => [
'block' => [
'blocktalk',
'2 hours',
'2 hours'
]
]
],
[
1 => [ 'warn' ],
2 => [ 'block' ]
],
],
];
}
}
Back to Directory
File Manager