Merge "Preferences: Remove href="#" from stub threshold sample link"
[lhc/web/wiklou.git] / tests / phpunit / includes / BlockTest.php
1 <?php
2
3 use MediaWiki\Block\BlockRestriction;
4 use MediaWiki\Block\Restriction\PageRestriction;
5 use MediaWiki\Block\Restriction\NamespaceRestriction;
6
7 /**
8 * @group Database
9 * @group Blocking
10 */
11 class BlockTest extends MediaWikiLangTestCase {
12
13 /**
14 * @return User
15 */
16 private function getUserForBlocking() {
17 $testUser = $this->getMutableTestUser();
18 $user = $testUser->getUser();
19 $user->addToDatabase();
20 TestUser::setPasswordForUser( $user, 'UTBlockeePassword' );
21 $user->saveSettings();
22 return $user;
23 }
24
25 /**
26 * @param User $user
27 *
28 * @return Block
29 * @throws MWException
30 */
31 private function addBlockForUser( User $user ) {
32 // Delete the last round's block if it's still there
33 $oldBlock = Block::newFromTarget( $user->getName() );
34 if ( $oldBlock ) {
35 // An old block will prevent our new one from saving.
36 $oldBlock->delete();
37 }
38
39 $blockOptions = [
40 'address' => $user->getName(),
41 'user' => $user->getId(),
42 'by' => $this->getTestSysop()->getUser()->getId(),
43 'reason' => 'Parce que',
44 'expiry' => time() + 100500,
45 ];
46 $block = new Block( $blockOptions );
47
48 $block->insert();
49 // save up ID for use in assertion. Since ID is an autoincrement,
50 // its value might change depending on the order the tests are run.
51 // ApiBlockTest insert its own blocks!
52 if ( !$block->getId() ) {
53 throw new MWException( "Failed to insert block for BlockTest; old leftover block remaining?" );
54 }
55
56 $this->addXffBlocks();
57
58 return $block;
59 }
60
61 /**
62 * @covers Block::newFromTarget
63 */
64 public function testINewFromTargetReturnsCorrectBlock() {
65 $user = $this->getUserForBlocking();
66 $block = $this->addBlockForUser( $user );
67
68 $this->assertTrue(
69 $block->equals( Block::newFromTarget( $user->getName() ) ),
70 "newFromTarget() returns the same block as the one that was made"
71 );
72 }
73
74 /**
75 * @covers Block::newFromID
76 */
77 public function testINewFromIDReturnsCorrectBlock() {
78 $user = $this->getUserForBlocking();
79 $block = $this->addBlockForUser( $user );
80
81 $this->assertTrue(
82 $block->equals( Block::newFromID( $block->getId() ) ),
83 "newFromID() returns the same block as the one that was made"
84 );
85 }
86
87 /**
88 * per T28425
89 * @covers Block::__construct
90 */
91 public function testT28425BlockTimestampDefaultsToTime() {
92 $user = $this->getUserForBlocking();
93 $block = $this->addBlockForUser( $user );
94 $madeAt = wfTimestamp( TS_MW );
95
96 // delta to stop one-off errors when things happen to go over a second mark.
97 $delta = abs( $madeAt - $block->mTimestamp );
98 $this->assertLessThan(
99 2,
100 $delta,
101 "If no timestamp is specified, the block is recorded as time()"
102 );
103 }
104
105 /**
106 * CheckUser since being changed to use Block::newFromTarget started failing
107 * because the new function didn't accept empty strings like Block::load()
108 * had. Regression T31116.
109 *
110 * @dataProvider provideT31116Data
111 * @covers Block::newFromTarget
112 */
113 public function testT31116NewFromTargetWithEmptyIp( $vagueTarget ) {
114 $user = $this->getUserForBlocking();
115 $initialBlock = $this->addBlockForUser( $user );
116 $block = Block::newFromTarget( $user->getName(), $vagueTarget );
117
118 $this->assertTrue(
119 $initialBlock->equals( $block ),
120 "newFromTarget() returns the same block as the one that was made when "
121 . "given empty vagueTarget param " . var_export( $vagueTarget, true )
122 );
123 }
124
125 public static function provideT31116Data() {
126 return [
127 [ null ],
128 [ '' ],
129 [ false ]
130 ];
131 }
132
133 /**
134 * @covers Block::appliesToRight
135 */
136 public function testBlockedUserCanNotCreateAccount() {
137 $username = 'BlockedUserToCreateAccountWith';
138 $u = User::newFromName( $username );
139 $u->addToDatabase();
140 $userId = $u->getId();
141 $this->assertNotEquals( 0, $userId, 'sanity' );
142 TestUser::setPasswordForUser( $u, 'NotRandomPass' );
143 unset( $u );
144
145 // Sanity check
146 $this->assertNull(
147 Block::newFromTarget( $username ),
148 "$username should not be blocked"
149 );
150
151 // Reload user
152 $u = User::newFromName( $username );
153 $this->assertFalse(
154 $u->isBlockedFromCreateAccount(),
155 "Our sandbox user should be able to create account before being blocked"
156 );
157
158 // Foreign perspective (blockee not on current wiki)...
159 $blockOptions = [
160 'address' => $username,
161 'user' => $userId,
162 'reason' => 'crosswiki block...',
163 'timestamp' => wfTimestampNow(),
164 'expiry' => $this->db->getInfinity(),
165 'createAccount' => true,
166 'enableAutoblock' => true,
167 'hideName' => true,
168 'blockEmail' => true,
169 'byText' => 'm>MetaWikiUser',
170 ];
171 $block = new Block( $blockOptions );
172 $block->insert();
173
174 // Reload block from DB
175 $userBlock = Block::newFromTarget( $username );
176 $this->assertTrue(
177 (bool)$block->appliesToRight( 'createaccount' ),
178 "Block object in DB should block right 'createaccount'"
179 );
180
181 $this->assertInstanceOf(
182 Block::class,
183 $userBlock,
184 "'$username' block block object should be existent"
185 );
186
187 // Reload user
188 $u = User::newFromName( $username );
189 $this->assertTrue(
190 (bool)$u->isBlockedFromCreateAccount(),
191 "Our sandbox user '$username' should NOT be able to create account"
192 );
193 }
194
195 /**
196 * @covers Block::insert
197 */
198 public function testCrappyCrossWikiBlocks() {
199 // Delete the last round's block if it's still there
200 $oldBlock = Block::newFromTarget( 'UserOnForeignWiki' );
201 if ( $oldBlock ) {
202 // An old block will prevent our new one from saving.
203 $oldBlock->delete();
204 }
205
206 // Local perspective (blockee on current wiki)...
207 $user = User::newFromName( 'UserOnForeignWiki' );
208 $user->addToDatabase();
209 $userId = $user->getId();
210 $this->assertNotEquals( 0, $userId, 'sanity' );
211
212 // Foreign perspective (blockee not on current wiki)...
213 $blockOptions = [
214 'address' => 'UserOnForeignWiki',
215 'user' => $user->getId(),
216 'reason' => 'crosswiki block...',
217 'timestamp' => wfTimestampNow(),
218 'expiry' => $this->db->getInfinity(),
219 'createAccount' => true,
220 'enableAutoblock' => true,
221 'hideName' => true,
222 'blockEmail' => true,
223 'byText' => 'Meta>MetaWikiUser',
224 ];
225 $block = new Block( $blockOptions );
226
227 $res = $block->insert( $this->db );
228 $this->assertTrue( (bool)$res['id'], 'Block succeeded' );
229
230 $user = null; // clear
231
232 $block = Block::newFromID( $res['id'] );
233 $this->assertEquals(
234 'UserOnForeignWiki',
235 $block->getTarget()->getName(),
236 'Correct blockee name'
237 );
238 $this->assertEquals( $userId, $block->getTarget()->getId(), 'Correct blockee id' );
239 $this->assertEquals( 'Meta>MetaWikiUser', $block->getBlocker()->getName(),
240 'Correct blocker name' );
241 $this->assertEquals( 'Meta>MetaWikiUser', $block->getByName(), 'Correct blocker name' );
242 $this->assertEquals( 0, $block->getBy(), 'Correct blocker id' );
243 }
244
245 protected function addXffBlocks() {
246 static $inited = false;
247
248 if ( $inited ) {
249 return;
250 }
251
252 $inited = true;
253
254 $blockList = [
255 [ 'target' => '70.2.0.0/16',
256 'type' => Block::TYPE_RANGE,
257 'desc' => 'Range Hardblock',
258 'ACDisable' => false,
259 'isHardblock' => true,
260 'isAutoBlocking' => false,
261 ],
262 [ 'target' => '2001:4860:4001::/48',
263 'type' => Block::TYPE_RANGE,
264 'desc' => 'Range6 Hardblock',
265 'ACDisable' => false,
266 'isHardblock' => true,
267 'isAutoBlocking' => false,
268 ],
269 [ 'target' => '60.2.0.0/16',
270 'type' => Block::TYPE_RANGE,
271 'desc' => 'Range Softblock with AC Disabled',
272 'ACDisable' => true,
273 'isHardblock' => false,
274 'isAutoBlocking' => false,
275 ],
276 [ 'target' => '50.2.0.0/16',
277 'type' => Block::TYPE_RANGE,
278 'desc' => 'Range Softblock',
279 'ACDisable' => false,
280 'isHardblock' => false,
281 'isAutoBlocking' => false,
282 ],
283 [ 'target' => '50.1.1.1',
284 'type' => Block::TYPE_IP,
285 'desc' => 'Exact Softblock',
286 'ACDisable' => false,
287 'isHardblock' => false,
288 'isAutoBlocking' => false,
289 ],
290 ];
291
292 $blocker = $this->getTestUser()->getUser();
293 foreach ( $blockList as $insBlock ) {
294 $target = $insBlock['target'];
295
296 if ( $insBlock['type'] === Block::TYPE_IP ) {
297 $target = User::newFromName( IP::sanitizeIP( $target ), false )->getName();
298 } elseif ( $insBlock['type'] === Block::TYPE_RANGE ) {
299 $target = IP::sanitizeRange( $target );
300 }
301
302 $block = new Block();
303 $block->setTarget( $target );
304 $block->setBlocker( $blocker );
305 $block->mReason = $insBlock['desc'];
306 $block->mExpiry = 'infinity';
307 $block->isCreateAccountBlocked( $insBlock['ACDisable'] );
308 $block->isHardblock( $insBlock['isHardblock'] );
309 $block->isAutoblocking( $insBlock['isAutoBlocking'] );
310 $block->insert();
311 }
312 }
313
314 public static function providerXff() {
315 return [
316 [ 'xff' => '1.2.3.4, 70.2.1.1, 60.2.1.1, 2.3.4.5',
317 'count' => 2,
318 'result' => 'Range Hardblock'
319 ],
320 [ 'xff' => '1.2.3.4, 50.2.1.1, 60.2.1.1, 2.3.4.5',
321 'count' => 2,
322 'result' => 'Range Softblock with AC Disabled'
323 ],
324 [ 'xff' => '1.2.3.4, 70.2.1.1, 50.1.1.1, 2.3.4.5',
325 'count' => 2,
326 'result' => 'Exact Softblock'
327 ],
328 [ 'xff' => '1.2.3.4, 70.2.1.1, 50.2.1.1, 50.1.1.1, 2.3.4.5',
329 'count' => 3,
330 'result' => 'Exact Softblock'
331 ],
332 [ 'xff' => '1.2.3.4, 70.2.1.1, 50.2.1.1, 2.3.4.5',
333 'count' => 2,
334 'result' => 'Range Hardblock'
335 ],
336 [ 'xff' => '1.2.3.4, 70.2.1.1, 60.2.1.1, 2.3.4.5',
337 'count' => 2,
338 'result' => 'Range Hardblock'
339 ],
340 [ 'xff' => '50.2.1.1, 60.2.1.1, 2.3.4.5',
341 'count' => 2,
342 'result' => 'Range Softblock with AC Disabled'
343 ],
344 [ 'xff' => '1.2.3.4, 50.1.1.1, 60.2.1.1, 2.3.4.5',
345 'count' => 2,
346 'result' => 'Exact Softblock'
347 ],
348 [ 'xff' => '1.2.3.4, <$A_BUNCH-OF{INVALID}TEXT\>, 60.2.1.1, 2.3.4.5',
349 'count' => 1,
350 'result' => 'Range Softblock with AC Disabled'
351 ],
352 [ 'xff' => '1.2.3.4, 50.2.1.1, 2001:4860:4001:802::1003, 2.3.4.5',
353 'count' => 2,
354 'result' => 'Range6 Hardblock'
355 ],
356 ];
357 }
358
359 /**
360 * @dataProvider providerXff
361 * @covers Block::getBlocksForIPList
362 * @covers Block::chooseBlock
363 */
364 public function testBlocksOnXff( $xff, $exCount, $exResult ) {
365 $user = $this->getUserForBlocking();
366 $this->addBlockForUser( $user );
367
368 $list = array_map( 'trim', explode( ',', $xff ) );
369 $xffblocks = Block::getBlocksForIPList( $list, true );
370 $this->assertEquals( $exCount, count( $xffblocks ), 'Number of blocks for ' . $xff );
371 $block = Block::chooseBlock( $xffblocks, $list );
372 $this->assertEquals( $exResult, $block->mReason, 'Correct block type for XFF header ' . $xff );
373 }
374
375 /**
376 * @covers Block::__construct
377 */
378 public function testDeprecatedConstructor() {
379 $this->hideDeprecated( 'Block::__construct with multiple arguments' );
380 $username = 'UnthinkablySecretRandomUsername';
381 $reason = 'being irrational';
382
383 # Set up the target
384 $u = User::newFromName( $username );
385 if ( $u->getId() == 0 ) {
386 $u->addToDatabase();
387 TestUser::setPasswordForUser( $u, 'TotallyObvious' );
388 }
389 unset( $u );
390
391 # Make sure the user isn't blocked
392 $this->assertNull(
393 Block::newFromTarget( $username ),
394 "$username should not be blocked"
395 );
396
397 # Perform the block
398 $block = new Block(
399 /* address */ $username,
400 /* user */ 0,
401 /* by */ $this->getTestSysop()->getUser()->getId(),
402 /* reason */ $reason,
403 /* timestamp */ 0,
404 /* auto */ false,
405 /* expiry */ 0
406 );
407 $block->insert();
408
409 # Check target
410 $this->assertEquals(
411 $block->getTarget()->getName(),
412 $username,
413 "Target should be set properly"
414 );
415
416 # Check supplied parameter
417 $this->assertEquals(
418 $block->mReason,
419 $reason,
420 "Reason should be non-default"
421 );
422
423 # Check default parameter
424 $this->assertFalse(
425 (bool)$block->appliesToRight( 'createaccount' ),
426 "Account creation should not be blocked by default"
427 );
428 }
429
430 /**
431 * @covers Block::getSystemBlockType
432 * @covers Block::insert
433 * @covers Block::doAutoblock
434 */
435 public function testSystemBlocks() {
436 $user = $this->getUserForBlocking();
437 $this->addBlockForUser( $user );
438
439 $blockOptions = [
440 'address' => $user->getName(),
441 'reason' => 'test system block',
442 'timestamp' => wfTimestampNow(),
443 'expiry' => $this->db->getInfinity(),
444 'byText' => 'MediaWiki default',
445 'systemBlock' => 'test',
446 'enableAutoblock' => true,
447 ];
448 $block = new Block( $blockOptions );
449
450 $this->assertSame( 'test', $block->getSystemBlockType() );
451
452 try {
453 $block->insert();
454 $this->fail( 'Expected exception not thrown' );
455 } catch ( MWException $ex ) {
456 $this->assertSame( 'Cannot insert a system block into the database', $ex->getMessage() );
457 }
458
459 try {
460 $block->doAutoblock( '192.0.2.2' );
461 $this->fail( 'Expected exception not thrown' );
462 } catch ( MWException $ex ) {
463 $this->assertSame( 'Cannot autoblock from a system block', $ex->getMessage() );
464 }
465 }
466
467 /**
468 * @covers Block::newFromRow
469 */
470 public function testNewFromRow() {
471 $badActor = $this->getTestUser()->getUser();
472 $sysop = $this->getTestSysop()->getUser();
473
474 $block = new Block( [
475 'address' => $badActor->getName(),
476 'user' => $badActor->getId(),
477 'by' => $sysop->getId(),
478 'expiry' => 'infinity',
479 ] );
480 $block->insert();
481
482 $blockQuery = Block::getQueryInfo();
483 $row = $this->db->select(
484 $blockQuery['tables'],
485 $blockQuery['fields'],
486 [
487 'ipb_id' => $block->getId(),
488 ],
489 __METHOD__,
490 [],
491 $blockQuery['joins']
492 )->fetchObject();
493
494 $block = Block::newFromRow( $row );
495 $this->assertInstanceOf( Block::class, $block );
496 $this->assertEquals( $block->getBy(), $sysop->getId() );
497 $this->assertEquals( $block->getTarget()->getName(), $badActor->getName() );
498 $block->delete();
499 }
500
501 /**
502 * @covers Block::equals
503 */
504 public function testEquals() {
505 $block = new Block();
506
507 $this->assertTrue( $block->equals( $block ) );
508
509 $partial = new Block( [
510 'sitewide' => false,
511 ] );
512 $this->assertFalse( $block->equals( $partial ) );
513 }
514
515 /**
516 * @covers Block::isSitewide
517 */
518 public function testIsSitewide() {
519 $block = new Block();
520 $this->assertTrue( $block->isSitewide() );
521
522 $block = new Block( [
523 'sitewide' => true,
524 ] );
525 $this->assertTrue( $block->isSitewide() );
526
527 $block = new Block( [
528 'sitewide' => false,
529 ] );
530 $this->assertFalse( $block->isSitewide() );
531
532 $block = new Block( [
533 'sitewide' => false,
534 ] );
535 $block->isSitewide( true );
536 $this->assertTrue( $block->isSitewide() );
537 }
538
539 /**
540 * @covers Block::getRestrictions
541 * @covers Block::setRestrictions
542 */
543 public function testRestrictions() {
544 $block = new Block();
545 $restrictions = [
546 new PageRestriction( 0, 1 )
547 ];
548 $block->setRestrictions( $restrictions );
549
550 $this->assertSame( $restrictions, $block->getRestrictions() );
551 }
552
553 /**
554 * @covers Block::getRestrictions
555 * @covers Block::insert
556 */
557 public function testRestrictionsFromDatabase() {
558 $badActor = $this->getTestUser()->getUser();
559 $sysop = $this->getTestSysop()->getUser();
560
561 $block = new Block( [
562 'address' => $badActor->getName(),
563 'user' => $badActor->getId(),
564 'by' => $sysop->getId(),
565 'expiry' => 'infinity',
566 ] );
567 $page = $this->getExistingTestPage( 'Foo' );
568 $restriction = new PageRestriction( 0, $page->getId() );
569 $block->setRestrictions( [ $restriction ] );
570 $block->insert();
571
572 // Refresh the block from the database.
573 $block = Block::newFromID( $block->getId() );
574 $restrictions = $block->getRestrictions();
575 $this->assertCount( 1, $restrictions );
576 $this->assertTrue( $restriction->equals( $restrictions[0] ) );
577 $block->delete();
578 }
579
580 /**
581 * @covers Block::insert
582 */
583 public function testInsertExistingBlock() {
584 $badActor = $this->getTestUser()->getUser();
585 $sysop = $this->getTestSysop()->getUser();
586
587 $block = new Block( [
588 'address' => $badActor->getName(),
589 'user' => $badActor->getId(),
590 'by' => $sysop->getId(),
591 'expiry' => 'infinity',
592 ] );
593 $page = $this->getExistingTestPage( 'Foo' );
594 $restriction = new PageRestriction( 0, $page->getId() );
595 $block->setRestrictions( [ $restriction ] );
596 $block->insert();
597
598 // Insert the block again, which should result in a failur
599 $result = $block->insert();
600
601 $this->assertFalse( $result );
602
603 // Ensure that there are no restrictions where the blockId is 0.
604 $count = $this->db->selectRowCount(
605 'ipblocks_restrictions',
606 '*',
607 [ 'ir_ipb_id' => 0 ],
608 __METHOD__
609 );
610 $this->assertSame( 0, $count );
611
612 $block->delete();
613 }
614
615 /**
616 * @covers Block::appliesToTitle
617 */
618 public function testAppliesToTitleReturnsTrueOnSitewideBlock() {
619 $this->setMwGlobals( [
620 'wgBlockDisablesLogin' => false,
621 ] );
622 $user = $this->getTestUser()->getUser();
623 $block = new Block( [
624 'expiry' => wfTimestamp( TS_MW, wfTimestamp() + ( 40 * 60 * 60 ) ),
625 'allowUsertalk' => true,
626 'sitewide' => true
627 ] );
628
629 $block->setTarget( $user );
630 $block->setBlocker( $this->getTestSysop()->getUser() );
631 $block->insert();
632
633 $title = $this->getExistingTestPage( 'Foo' )->getTitle();
634
635 $this->assertTrue( $block->appliesToTitle( $title ) );
636
637 // appliesToTitle() ignores allowUsertalk
638 $title = $user->getTalkPage();
639 $this->assertTrue( $block->appliesToTitle( $title ) );
640
641 $block->delete();
642 }
643
644 /**
645 * @covers Block::appliesToTitle
646 */
647 public function testAppliesToTitleOnPartialBlock() {
648 $this->setMwGlobals( [
649 'wgBlockDisablesLogin' => false,
650 ] );
651 $user = $this->getTestUser()->getUser();
652 $block = new Block( [
653 'expiry' => wfTimestamp( TS_MW, wfTimestamp() + ( 40 * 60 * 60 ) ),
654 'allowUsertalk' => true,
655 'sitewide' => false
656 ] );
657
658 $block->setTarget( $user );
659 $block->setBlocker( $this->getTestSysop()->getUser() );
660 $block->insert();
661
662 $pageFoo = $this->getExistingTestPage( 'Foo' );
663 $pageBar = $this->getExistingTestPage( 'Bar' );
664 $pageJohn = $this->getExistingTestPage( 'User:John' );
665
666 $pageRestriction = new PageRestriction( $block->getId(), $pageFoo->getId() );
667 $namespaceRestriction = new NamespaceRestriction( $block->getId(), NS_USER );
668 BlockRestriction::insert( [ $pageRestriction, $namespaceRestriction ] );
669
670 $this->assertTrue( $block->appliesToTitle( $pageFoo->getTitle() ) );
671 $this->assertFalse( $block->appliesToTitle( $pageBar->getTitle() ) );
672 $this->assertTrue( $block->appliesToTitle( $pageJohn->getTitle() ) );
673
674 $block->delete();
675 }
676
677 /**
678 * @covers Block::appliesToNamespace
679 * @covers Block::appliesToPage
680 */
681 public function testAppliesToReturnsTrueOnSitewideBlock() {
682 $this->setMwGlobals( [
683 'wgBlockDisablesLogin' => false,
684 ] );
685 $user = $this->getTestUser()->getUser();
686 $block = new Block( [
687 'expiry' => wfTimestamp( TS_MW, wfTimestamp() + ( 40 * 60 * 60 ) ),
688 'allowUsertalk' => true,
689 'sitewide' => true
690 ] );
691
692 $block->setTarget( $user );
693 $block->setBlocker( $this->getTestSysop()->getUser() );
694 $block->insert();
695
696 $title = $this->getExistingTestPage()->getTitle();
697
698 $this->assertTrue( $block->appliesToPage( $title->getArticleID() ) );
699 $this->assertTrue( $block->appliesToNamespace( NS_MAIN ) );
700 $this->assertTrue( $block->appliesToNamespace( NS_USER_TALK ) );
701
702 $block->delete();
703 }
704
705 /**
706 * @covers Block::appliesToPage
707 */
708 public function testAppliesToPageOnPartialPageBlock() {
709 $this->setMwGlobals( [
710 'wgBlockDisablesLogin' => false,
711 ] );
712 $user = $this->getTestUser()->getUser();
713 $block = new Block( [
714 'expiry' => wfTimestamp( TS_MW, wfTimestamp() + ( 40 * 60 * 60 ) ),
715 'allowUsertalk' => true,
716 'sitewide' => false
717 ] );
718
719 $block->setTarget( $user );
720 $block->setBlocker( $this->getTestSysop()->getUser() );
721 $block->insert();
722
723 $title = $this->getExistingTestPage()->getTitle();
724
725 $pageRestriction = new PageRestriction(
726 $block->getId(),
727 $title->getArticleID()
728 );
729 BlockRestriction::insert( [ $pageRestriction ] );
730
731 $this->assertTrue( $block->appliesToPage( $title->getArticleID() ) );
732
733 $block->delete();
734 }
735
736 /**
737 * @covers Block::appliesToNamespace
738 */
739 public function testAppliesToNamespaceOnPartialNamespaceBlock() {
740 $this->setMwGlobals( [
741 'wgBlockDisablesLogin' => false,
742 ] );
743 $user = $this->getTestUser()->getUser();
744 $block = new Block( [
745 'expiry' => wfTimestamp( TS_MW, wfTimestamp() + ( 40 * 60 * 60 ) ),
746 'allowUsertalk' => true,
747 'sitewide' => false
748 ] );
749
750 $block->setTarget( $user );
751 $block->setBlocker( $this->getTestSysop()->getUser() );
752 $block->insert();
753
754 $namespaceRestriction = new NamespaceRestriction( $block->getId(), NS_MAIN );
755 BlockRestriction::insert( [ $namespaceRestriction ] );
756
757 $this->assertTrue( $block->appliesToNamespace( NS_MAIN ) );
758 $this->assertFalse( $block->appliesToNamespace( NS_USER ) );
759
760 $block->delete();
761 }
762
763 /**
764 * @covers Block::appliesToRight
765 */
766 public function testBlockAllowsPurge() {
767 $this->setMwGlobals( [
768 'wgBlockDisablesLogin' => false,
769 ] );
770 $block = new Block();
771 $this->assertFalse( $block->appliesToRight( 'purge' ) );
772 }
773
774 }