3 use MediaWiki\Block\BlockRestriction
;
4 use MediaWiki\Block\Restriction\PageRestriction
;
5 use MediaWiki\Block\Restriction\NamespaceRestriction
;
6 use Wikimedia\TestingAccessWrapper
;
11 * @coversDefaultClass SpecialBlock
13 class SpecialBlockTest
extends SpecialPageTestBase
{
17 protected function newSpecialPage() {
18 return new SpecialBlock();
21 public function tearDown() {
27 * @covers ::getFormFields()
29 public function testGetFormFields() {
30 $this->setMwGlobals( [
31 'wgEnablePartialBlocks' => false,
33 $page = $this->newSpecialPage();
34 $wrappedPage = TestingAccessWrapper
::newFromObject( $page );
35 $fields = $wrappedPage->getFormFields();
36 $this->assertInternalType( 'array', $fields );
37 $this->assertArrayHasKey( 'Target', $fields );
38 $this->assertArrayHasKey( 'Expiry', $fields );
39 $this->assertArrayHasKey( 'Reason', $fields );
40 $this->assertArrayHasKey( 'CreateAccount', $fields );
41 $this->assertArrayHasKey( 'DisableUTEdit', $fields );
42 $this->assertArrayHasKey( 'AutoBlock', $fields );
43 $this->assertArrayHasKey( 'HardBlock', $fields );
44 $this->assertArrayHasKey( 'PreviousTarget', $fields );
45 $this->assertArrayHasKey( 'Confirm', $fields );
47 $this->assertArrayNotHasKey( 'EditingRestriction', $fields );
48 $this->assertArrayNotHasKey( 'PageRestrictions', $fields );
49 $this->assertArrayNotHasKey( 'NamespaceRestrictions', $fields );
53 * @covers ::getFormFields()
55 public function testGetFormFieldsPartialBlocks() {
56 $this->setMwGlobals( [
57 'wgEnablePartialBlocks' => true,
59 $page = $this->newSpecialPage();
60 $wrappedPage = TestingAccessWrapper
::newFromObject( $page );
61 $fields = $wrappedPage->getFormFields();
63 $this->assertArrayHasKey( 'EditingRestriction', $fields );
64 $this->assertArrayHasKey( 'PageRestrictions', $fields );
65 $this->assertArrayHasKey( 'NamespaceRestrictions', $fields );
69 * @covers ::maybeAlterFormDefaults()
71 public function testMaybeAlterFormDefaults() {
72 $this->setMwGlobals( [
73 'wgEnablePartialBlocks' => false,
76 $block = $this->insertBlock();
78 // Refresh the block from the database.
79 $block = Block
::newFromTarget( $block->getTarget() );
81 $page = $this->newSpecialPage();
83 $wrappedPage = TestingAccessWrapper
::newFromObject( $page );
84 $wrappedPage->target
= $block->getTarget();
85 $fields = $wrappedPage->getFormFields();
87 $this->assertSame( (string)$block->getTarget(), $fields['Target']['default'] );
88 $this->assertSame( $block->isHardblock(), $fields['HardBlock']['default'] );
89 $this->assertSame( $block->prevents( 'createaccount' ), $fields['CreateAccount']['default'] );
90 $this->assertSame( $block->isAutoblocking(), $fields['AutoBlock']['default'] );
91 $this->assertSame( $block->prevents( 'editownusertalk' ), $fields['DisableUTEdit']['default'] );
92 $this->assertSame( $block->mReason
, $fields['Reason']['default'] );
93 $this->assertSame( 'infinite', $fields['Expiry']['default'] );
97 * @covers ::maybeAlterFormDefaults()
99 public function testMaybeAlterFormDefaultsPartial() {
100 $this->setMwGlobals( [
101 'wgEnablePartialBlocks' => true,
104 $badActor = $this->getTestUser()->getUser();
105 $sysop = $this->getTestSysop()->getUser();
106 $pageSaturn = $this->getExistingTestPage( 'Saturn' );
107 $pageMars = $this->getExistingTestPage( 'Mars' );
109 $block = new \
Block( [
110 'address' => $badActor->getName(),
111 'user' => $badActor->getId(),
112 'by' => $sysop->getId(),
113 'expiry' => 'infinity',
115 'enableAutoblock' => true,
118 $block->setRestrictions( [
119 new PageRestriction( 0, $pageSaturn->getId() ),
120 new PageRestriction( 0, $pageMars->getId() ),
121 new NamespaceRestriction( 0, NS_TALK
),
126 // Refresh the block from the database.
127 $block = Block
::newFromTarget( $block->getTarget() );
129 $page = $this->newSpecialPage();
131 $wrappedPage = TestingAccessWrapper
::newFromObject( $page );
132 $wrappedPage->target
= $block->getTarget();
133 $fields = $wrappedPage->getFormFields();
136 $pageMars->getTitle()->getPrefixedText(),
137 $pageSaturn->getTitle()->getPrefixedText(),
140 $this->assertSame( (string)$block->getTarget(), $fields['Target']['default'] );
141 $this->assertSame( 'partial', $fields['EditingRestriction']['default'] );
142 $this->assertSame( implode( "\n", $titles ), $fields['PageRestrictions']['default'] );
146 * @covers ::processForm()
148 public function testProcessForm() {
149 $this->setMwGlobals( [
150 'wgEnablePartialBlocks' => false,
152 $badActor = $this->getTestUser()->getUser();
153 $context = RequestContext
::getMain();
155 $page = $this->newSpecialPage();
157 $expiry = 'infinity';
159 'Target' => (string)$badActor,
160 'Expiry' => 'infinity',
165 'CreateAccount' => '0',
166 'DisableUTEdit' => '0',
167 'DisableEmail' => '0',
173 $result = $page->processForm( $data, $context );
175 $this->assertTrue( $result );
177 $block = Block
::newFromTarget( $badActor );
178 $this->assertSame( $reason, $block->mReason
);
179 $this->assertSame( $expiry, $block->getExpiry() );
183 * @covers ::processForm()
185 public function testProcessFormExisting() {
186 $this->setMwGlobals( [
187 'wgEnablePartialBlocks' => false,
189 $badActor = $this->getTestUser()->getUser();
190 $sysop = $this->getTestSysop()->getUser();
191 $context = RequestContext
::getMain();
193 // Create a block that will be updated.
194 $block = new \
Block( [
195 'address' => $badActor->getName(),
196 'user' => $badActor->getId(),
197 'by' => $sysop->getId(),
198 'expiry' => 'infinity',
200 'enableAutoblock' => false,
204 $page = $this->newSpecialPage();
206 $expiry = 'infinity';
208 'Target' => (string)$badActor,
209 'Expiry' => 'infinity',
214 'CreateAccount' => '0',
215 'DisableUTEdit' => '0',
216 'DisableEmail' => '0',
222 $result = $page->processForm( $data, $context );
224 $this->assertTrue( $result );
226 $block = Block
::newFromTarget( $badActor );
227 $this->assertSame( $reason, $block->mReason
);
228 $this->assertSame( $expiry, $block->getExpiry() );
229 $this->assertSame( '1', $block->isAutoblocking() );
233 * @covers ::processForm()
235 public function testProcessFormRestrictions() {
236 $this->setMwGlobals( [
237 'wgEnablePartialBlocks' => true,
239 $badActor = $this->getTestUser()->getUser();
240 $context = RequestContext
::getMain();
242 $pageSaturn = $this->getExistingTestPage( 'Saturn' );
243 $pageMars = $this->getExistingTestPage( 'Mars' );
246 $pageSaturn->getTitle()->getText(),
247 $pageMars->getTitle()->getText(),
250 $page = $this->newSpecialPage();
252 $expiry = 'infinity';
254 'Target' => (string)$badActor,
255 'Expiry' => 'infinity',
260 'CreateAccount' => '0',
261 'DisableUTEdit' => '0',
262 'DisableEmail' => '0',
267 'EditingRestriction' => 'partial',
268 'PageRestrictions' => implode( "\n", $titles ),
269 'NamespaceRestrictions' => '',
271 $result = $page->processForm( $data, $context );
273 $this->assertTrue( $result );
275 $block = Block
::newFromTarget( $badActor );
276 $this->assertSame( $reason, $block->mReason
);
277 $this->assertSame( $expiry, $block->getExpiry() );
278 $this->assertCount( 2, $block->getRestrictions() );
279 $this->assertTrue( BlockRestriction
::equals( $block->getRestrictions(), [
280 new PageRestriction( $block->getId(), $pageMars->getId() ),
281 new PageRestriction( $block->getId(), $pageSaturn->getId() ),
286 * @covers ::processForm()
288 public function testProcessFormRestrictionsChange() {
289 $this->setMwGlobals( [
290 'wgEnablePartialBlocks' => true,
292 $badActor = $this->getTestUser()->getUser();
293 $context = RequestContext
::getMain();
295 $pageSaturn = $this->getExistingTestPage( 'Saturn' );
296 $pageMars = $this->getExistingTestPage( 'Mars' );
299 $pageSaturn->getTitle()->getText(),
300 $pageMars->getTitle()->getText(),
303 // Create a partial block.
304 $page = $this->newSpecialPage();
306 $expiry = 'infinity';
308 'Target' => (string)$badActor,
309 'Expiry' => 'infinity',
314 'CreateAccount' => '0',
315 'DisableUTEdit' => '0',
316 'DisableEmail' => '0',
321 'EditingRestriction' => 'partial',
322 'PageRestrictions' => implode( "\n", $titles ),
323 'NamespaceRestrictions' => '',
325 $result = $page->processForm( $data, $context );
327 $this->assertTrue( $result );
329 $block = Block
::newFromTarget( $badActor );
330 $this->assertSame( $reason, $block->mReason
);
331 $this->assertSame( $expiry, $block->getExpiry() );
332 $this->assertFalse( $block->isSitewide() );
333 $this->assertCount( 2, $block->getRestrictions() );
334 $this->assertTrue( BlockRestriction
::equals( $block->getRestrictions(), [
335 new PageRestriction( $block->getId(), $pageMars->getId() ),
336 new PageRestriction( $block->getId(), $pageSaturn->getId() ),
339 // Remove a page from the partial block.
340 $data['PageRestrictions'] = $pageMars->getTitle()->getText();
341 $result = $page->processForm( $data, $context );
343 $this->assertTrue( $result );
345 $block = Block
::newFromTarget( $badActor );
346 $this->assertSame( $reason, $block->mReason
);
347 $this->assertSame( $expiry, $block->getExpiry() );
348 $this->assertFalse( $block->isSitewide() );
349 $this->assertCount( 1, $block->getRestrictions() );
350 $this->assertTrue( BlockRestriction
::equals( $block->getRestrictions(), [
351 new PageRestriction( $block->getId(), $pageMars->getId() ),
354 // Remove the last page from the block.
355 $data['PageRestrictions'] = '';
356 $result = $page->processForm( $data, $context );
358 $this->assertTrue( $result );
360 $block = Block
::newFromTarget( $badActor );
361 $this->assertSame( $reason, $block->mReason
);
362 $this->assertSame( $expiry, $block->getExpiry() );
363 $this->assertFalse( $block->isSitewide() );
364 $this->assertCount( 0, $block->getRestrictions() );
366 // Change to sitewide.
367 $data['EditingRestriction'] = 'sitewide';
368 $result = $page->processForm( $data, $context );
370 $this->assertTrue( $result );
372 $block = Block
::newFromTarget( $badActor );
373 $this->assertSame( $reason, $block->mReason
);
374 $this->assertSame( $expiry, $block->getExpiry() );
375 $this->assertTrue( $block->isSitewide() );
376 $this->assertCount( 0, $block->getRestrictions() );
378 // Ensure that there are no restrictions where the blockId is 0.
379 $count = $this->db
->selectRowCount(
380 'ipblocks_restrictions',
382 [ 'ir_ipb_id' => 0 ],
385 $this->assertSame( 0, $count );
389 * @dataProvider provideCheckUnblockSelf
390 * @covers ::checkUnblockSelf
392 public function testCheckUnblockSelf(
400 $this->setGroupPermissions( 'sysop', 'unblockself', true );
401 $this->setGroupPermissions( 'user', 'block', true );
402 // Getting errors about creating users in db in provider.
403 // Need to use mutable to ensure different named testusers.
405 'u1' => TestUserRegistry
::getMutableTestUser( __CLASS__
, 'sysop' )->getUser(),
406 'u2' => TestUserRegistry
::getMutableTestUser( __CLASS__
, 'sysop' )->getUser(),
407 'u3' => TestUserRegistry
::getMutableTestUser( __CLASS__
, 'sysop' )->getUser(),
408 'u4' => TestUserRegistry
::getMutableTestUser( __CLASS__
, 'sysop' )->getUser(),
409 'nonsysop' => $this->getTestUser()->getUser()
411 foreach ( [ 'blockedUser', 'blockPerformer', 'adjustPerformer', 'adjustTarget' ] as $var ) {
412 $
$var = $users[$
$var];
415 $block = new \
Block( [
416 'address' => $blockedUser->getName(),
417 'user' => $blockedUser->getId(),
418 'by' => $blockPerformer->getId(),
419 'expiry' => 'infinity',
421 'enableAutoblock' => true,
427 SpecialBlock
::checkUnblockSelf( $adjustTarget, $adjustPerformer ),
433 public function provideCheckUnblockSelf() {
434 // 'blockedUser', 'blockPerformer', 'adjustPerformer', 'adjustTarget'
436 [ 'u1', 'u2', 'u3', 'u4', true, 'Unrelated users' ],
437 [ 'u1', 'u2', 'u1', 'u4', 'ipbblocked', 'Block unrelated while blocked' ],
438 [ 'u1', 'u2', 'u1', 'u1', true, 'Has unblockself' ],
439 [ 'nonsysop', 'u2', 'nonsysop', 'nonsysop', 'ipbnounblockself', 'no unblockself' ],
440 [ 'nonsysop', 'nonsysop', 'nonsysop', 'nonsysop', true, 'no unblockself but can de-selfblock' ],
441 [ 'u1', 'u2', 'u1', 'u2', true, 'Can block user who blocked' ],
445 protected function insertBlock() {
446 $badActor = $this->getTestUser()->getUser();
447 $sysop = $this->getTestSysop()->getUser();
449 $block = new \
Block( [
450 'address' => $badActor->getName(),
451 'user' => $badActor->getId(),
452 'by' => $sysop->getId(),
453 'expiry' => 'infinity',
455 'enableAutoblock' => true,
463 protected function resetTables() {
464 $this->db
->delete( 'ipblocks', '*', __METHOD__
);
465 $this->db
->delete( 'ipblocks_restrictions', '*', __METHOD__
);