Merge "Synchronize allowed attributes for <audio> with Parsoid/TimedMediaHandler"
[lhc/web/wiklou.git] / tests / phpunit / includes / specials / SpecialBlockTest.php
1 <?php
2
3 use MediaWiki\Block\BlockRestrictionStore;
4 use MediaWiki\Block\Restriction\PageRestriction;
5 use MediaWiki\Block\Restriction\NamespaceRestriction;
6 use Wikimedia\TestingAccessWrapper;
7 use Wikimedia\Rdbms\LoadBalancer;
8
9 /**
10 * @group Blocking
11 * @group Database
12 * @coversDefaultClass SpecialBlock
13 */
14 class SpecialBlockTest extends SpecialPageTestBase {
15 /**
16 * @inheritDoc
17 */
18 protected function newSpecialPage() {
19 return new SpecialBlock();
20 }
21
22 public function tearDown() {
23 parent::tearDown();
24 $this->resetTables();
25 }
26
27 /**
28 * @covers ::getFormFields()
29 */
30 public function testGetFormFields() {
31 $this->setMwGlobals( [
32 'wgEnablePartialBlocks' => false,
33 'wgBlockAllowsUTEdit' => true,
34 ] );
35 $page = $this->newSpecialPage();
36 $wrappedPage = TestingAccessWrapper::newFromObject( $page );
37 $fields = $wrappedPage->getFormFields();
38 $this->assertInternalType( 'array', $fields );
39 $this->assertArrayHasKey( 'Target', $fields );
40 $this->assertArrayHasKey( 'Expiry', $fields );
41 $this->assertArrayHasKey( 'Reason', $fields );
42 $this->assertArrayHasKey( 'CreateAccount', $fields );
43 $this->assertArrayHasKey( 'DisableUTEdit', $fields );
44 $this->assertArrayHasKey( 'AutoBlock', $fields );
45 $this->assertArrayHasKey( 'HardBlock', $fields );
46 $this->assertArrayHasKey( 'PreviousTarget', $fields );
47 $this->assertArrayHasKey( 'Confirm', $fields );
48
49 $this->assertArrayNotHasKey( 'EditingRestriction', $fields );
50 $this->assertArrayNotHasKey( 'PageRestrictions', $fields );
51 $this->assertArrayNotHasKey( 'NamespaceRestrictions', $fields );
52 }
53
54 /**
55 * @covers ::getFormFields()
56 */
57 public function testGetFormFieldsPartialBlocks() {
58 $this->setMwGlobals( [
59 'wgEnablePartialBlocks' => true,
60 ] );
61 $page = $this->newSpecialPage();
62 $wrappedPage = TestingAccessWrapper::newFromObject( $page );
63 $fields = $wrappedPage->getFormFields();
64
65 $this->assertArrayHasKey( 'EditingRestriction', $fields );
66 $this->assertArrayHasKey( 'PageRestrictions', $fields );
67 $this->assertArrayHasKey( 'NamespaceRestrictions', $fields );
68 }
69
70 /**
71 * @covers ::maybeAlterFormDefaults()
72 */
73 public function testMaybeAlterFormDefaults() {
74 $this->setMwGlobals( [
75 'wgEnablePartialBlocks' => false,
76 'wgBlockAllowsUTEdit' => true,
77 ] );
78
79 $block = $this->insertBlock();
80
81 // Refresh the block from the database.
82 $block = Block::newFromTarget( $block->getTarget() );
83
84 $page = $this->newSpecialPage();
85
86 $wrappedPage = TestingAccessWrapper::newFromObject( $page );
87 $wrappedPage->target = $block->getTarget();
88 $fields = $wrappedPage->getFormFields();
89
90 $this->assertSame( (string)$block->getTarget(), $fields['Target']['default'] );
91 $this->assertSame( $block->isHardblock(), $fields['HardBlock']['default'] );
92 $this->assertSame( $block->isCreateAccountBlocked(), $fields['CreateAccount']['default'] );
93 $this->assertSame( $block->isAutoblocking(), $fields['AutoBlock']['default'] );
94 $this->assertSame( !$block->isUsertalkEditAllowed(), $fields['DisableUTEdit']['default'] );
95 $this->assertSame( $block->getReason(), $fields['Reason']['default'] );
96 $this->assertSame( 'infinite', $fields['Expiry']['default'] );
97 }
98
99 /**
100 * @covers ::maybeAlterFormDefaults()
101 */
102 public function testMaybeAlterFormDefaultsPartial() {
103 $this->setMwGlobals( [
104 'wgEnablePartialBlocks' => true,
105 ] );
106
107 $badActor = $this->getTestUser()->getUser();
108 $sysop = $this->getTestSysop()->getUser();
109 $pageSaturn = $this->getExistingTestPage( 'Saturn' );
110 $pageMars = $this->getExistingTestPage( 'Mars' );
111
112 $block = new \Block( [
113 'address' => $badActor->getName(),
114 'user' => $badActor->getId(),
115 'by' => $sysop->getId(),
116 'expiry' => 'infinity',
117 'sitewide' => 0,
118 'enableAutoblock' => true,
119 ] );
120
121 $block->setRestrictions( [
122 new PageRestriction( 0, $pageSaturn->getId() ),
123 new PageRestriction( 0, $pageMars->getId() ),
124 new NamespaceRestriction( 0, NS_TALK ),
125 // Deleted page.
126 new PageRestriction( 0, 999999 ),
127 ] );
128
129 $block->insert();
130
131 // Refresh the block from the database.
132 $block = Block::newFromTarget( $block->getTarget() );
133
134 $page = $this->newSpecialPage();
135
136 $wrappedPage = TestingAccessWrapper::newFromObject( $page );
137 $wrappedPage->target = $block->getTarget();
138 $fields = $wrappedPage->getFormFields();
139
140 $titles = [
141 $pageMars->getTitle()->getPrefixedText(),
142 $pageSaturn->getTitle()->getPrefixedText(),
143 ];
144
145 $this->assertSame( (string)$block->getTarget(), $fields['Target']['default'] );
146 $this->assertSame( 'partial', $fields['EditingRestriction']['default'] );
147 $this->assertSame( implode( "\n", $titles ), $fields['PageRestrictions']['default'] );
148 }
149
150 /**
151 * @covers ::processForm()
152 */
153 public function testProcessForm() {
154 $this->setMwGlobals( [
155 'wgEnablePartialBlocks' => false,
156 ] );
157 $badActor = $this->getTestUser()->getUser();
158 $context = RequestContext::getMain();
159
160 $page = $this->newSpecialPage();
161 $reason = 'test';
162 $expiry = 'infinity';
163 $data = [
164 'Target' => (string)$badActor,
165 'Expiry' => 'infinity',
166 'Reason' => [
167 $reason,
168 ],
169 'Confirm' => '1',
170 'CreateAccount' => '0',
171 'DisableUTEdit' => '0',
172 'DisableEmail' => '0',
173 'HardBlock' => '0',
174 'AutoBlock' => '1',
175 'HideUser' => '0',
176 'Watch' => '0',
177 ];
178 $result = $page->processForm( $data, $context );
179
180 $this->assertTrue( $result );
181
182 $block = Block::newFromTarget( $badActor );
183 $this->assertSame( $reason, $block->getReason() );
184 $this->assertSame( $expiry, $block->getExpiry() );
185 }
186
187 /**
188 * @covers ::processForm()
189 */
190 public function testProcessFormExisting() {
191 $this->setMwGlobals( [
192 'wgEnablePartialBlocks' => false,
193 ] );
194 $badActor = $this->getTestUser()->getUser();
195 $sysop = $this->getTestSysop()->getUser();
196 $context = RequestContext::getMain();
197
198 // Create a block that will be updated.
199 $block = new \Block( [
200 'address' => $badActor->getName(),
201 'user' => $badActor->getId(),
202 'by' => $sysop->getId(),
203 'expiry' => 'infinity',
204 'sitewide' => 0,
205 'enableAutoblock' => false,
206 ] );
207 $block->insert();
208
209 $page = $this->newSpecialPage();
210 $reason = 'test';
211 $expiry = 'infinity';
212 $data = [
213 'Target' => (string)$badActor,
214 'Expiry' => 'infinity',
215 'Reason' => [
216 $reason,
217 ],
218 'Confirm' => '1',
219 'CreateAccount' => '0',
220 'DisableUTEdit' => '0',
221 'DisableEmail' => '0',
222 'HardBlock' => '0',
223 'AutoBlock' => '1',
224 'HideUser' => '0',
225 'Watch' => '0',
226 ];
227 $result = $page->processForm( $data, $context );
228
229 $this->assertTrue( $result );
230
231 $block = Block::newFromTarget( $badActor );
232 $this->assertSame( $reason, $block->getReason() );
233 $this->assertSame( $expiry, $block->getExpiry() );
234 $this->assertSame( '1', $block->isAutoblocking() );
235 }
236
237 /**
238 * @covers ::processForm()
239 */
240 public function testProcessFormRestrictions() {
241 $this->setMwGlobals( [
242 'wgEnablePartialBlocks' => true,
243 ] );
244 $badActor = $this->getTestUser()->getUser();
245 $context = RequestContext::getMain();
246
247 $pageSaturn = $this->getExistingTestPage( 'Saturn' );
248 $pageMars = $this->getExistingTestPage( 'Mars' );
249
250 $titles = [
251 $pageSaturn->getTitle()->getText(),
252 $pageMars->getTitle()->getText(),
253 ];
254
255 $page = $this->newSpecialPage();
256 $reason = 'test';
257 $expiry = 'infinity';
258 $data = [
259 'Target' => (string)$badActor,
260 'Expiry' => 'infinity',
261 'Reason' => [
262 $reason,
263 ],
264 'Confirm' => '1',
265 'CreateAccount' => '0',
266 'DisableUTEdit' => '0',
267 'DisableEmail' => '0',
268 'HardBlock' => '0',
269 'AutoBlock' => '1',
270 'HideUser' => '0',
271 'Watch' => '0',
272 'EditingRestriction' => 'partial',
273 'PageRestrictions' => implode( "\n", $titles ),
274 'NamespaceRestrictions' => '',
275 ];
276 $result = $page->processForm( $data, $context );
277
278 $this->assertTrue( $result );
279
280 $block = Block::newFromTarget( $badActor );
281 $this->assertSame( $reason, $block->getReason() );
282 $this->assertSame( $expiry, $block->getExpiry() );
283 $this->assertCount( 2, $block->getRestrictions() );
284 $this->assertTrue( $this->getBlockRestrictionStore()->equals( $block->getRestrictions(), [
285 new PageRestriction( $block->getId(), $pageMars->getId() ),
286 new PageRestriction( $block->getId(), $pageSaturn->getId() ),
287 ] ) );
288 }
289
290 /**
291 * @covers ::processForm()
292 */
293 public function testProcessFormRestrictionsChange() {
294 $this->setMwGlobals( [
295 'wgEnablePartialBlocks' => true,
296 ] );
297 $badActor = $this->getTestUser()->getUser();
298 $context = RequestContext::getMain();
299
300 $pageSaturn = $this->getExistingTestPage( 'Saturn' );
301 $pageMars = $this->getExistingTestPage( 'Mars' );
302
303 $titles = [
304 $pageSaturn->getTitle()->getText(),
305 $pageMars->getTitle()->getText(),
306 ];
307
308 // Create a partial block.
309 $page = $this->newSpecialPage();
310 $reason = 'test';
311 $expiry = 'infinity';
312 $data = [
313 'Target' => (string)$badActor,
314 'Expiry' => 'infinity',
315 'Reason' => [
316 $reason,
317 ],
318 'Confirm' => '1',
319 'CreateAccount' => '0',
320 'DisableUTEdit' => '0',
321 'DisableEmail' => '0',
322 'HardBlock' => '0',
323 'AutoBlock' => '1',
324 'HideUser' => '0',
325 'Watch' => '0',
326 'EditingRestriction' => 'partial',
327 'PageRestrictions' => implode( "\n", $titles ),
328 'NamespaceRestrictions' => '',
329 ];
330 $result = $page->processForm( $data, $context );
331
332 $this->assertTrue( $result );
333
334 $block = Block::newFromTarget( $badActor );
335 $this->assertSame( $reason, $block->getReason() );
336 $this->assertSame( $expiry, $block->getExpiry() );
337 $this->assertFalse( $block->isSitewide() );
338 $this->assertCount( 2, $block->getRestrictions() );
339 $this->assertTrue( $this->getBlockRestrictionStore()->equals( $block->getRestrictions(), [
340 new PageRestriction( $block->getId(), $pageMars->getId() ),
341 new PageRestriction( $block->getId(), $pageSaturn->getId() ),
342 ] ) );
343
344 // Remove a page from the partial block.
345 $data['PageRestrictions'] = $pageMars->getTitle()->getText();
346 $result = $page->processForm( $data, $context );
347
348 $this->assertTrue( $result );
349
350 $block = Block::newFromTarget( $badActor );
351 $this->assertSame( $reason, $block->getReason() );
352 $this->assertSame( $expiry, $block->getExpiry() );
353 $this->assertFalse( $block->isSitewide() );
354 $this->assertCount( 1, $block->getRestrictions() );
355 $this->assertTrue( $this->getBlockRestrictionStore()->equals( $block->getRestrictions(), [
356 new PageRestriction( $block->getId(), $pageMars->getId() ),
357 ] ) );
358
359 // Remove the last page from the block.
360 $data['PageRestrictions'] = '';
361 $result = $page->processForm( $data, $context );
362
363 $this->assertTrue( $result );
364
365 $block = Block::newFromTarget( $badActor );
366 $this->assertSame( $reason, $block->getReason() );
367 $this->assertSame( $expiry, $block->getExpiry() );
368 $this->assertFalse( $block->isSitewide() );
369 $this->assertCount( 0, $block->getRestrictions() );
370
371 // Change to sitewide.
372 $data['EditingRestriction'] = 'sitewide';
373 $result = $page->processForm( $data, $context );
374
375 $this->assertTrue( $result );
376
377 $block = Block::newFromTarget( $badActor );
378 $this->assertSame( $reason, $block->getReason() );
379 $this->assertSame( $expiry, $block->getExpiry() );
380 $this->assertTrue( $block->isSitewide() );
381 $this->assertCount( 0, $block->getRestrictions() );
382
383 // Ensure that there are no restrictions where the blockId is 0.
384 $count = $this->db->selectRowCount(
385 'ipblocks_restrictions',
386 '*',
387 [ 'ir_ipb_id' => 0 ],
388 __METHOD__
389 );
390 $this->assertSame( 0, $count );
391 }
392
393 /**
394 * @dataProvider provideCheckUnblockSelf
395 * @covers ::checkUnblockSelf
396 */
397 public function testCheckUnblockSelf(
398 $blockedUser,
399 $blockPerformer,
400 $adjustPerformer,
401 $adjustTarget,
402 $expectedResult,
403 $reason
404 ) {
405 $this->setMwGlobals( [
406 'wgBlockDisablesLogin' => false,
407 ] );
408 $this->setGroupPermissions( 'sysop', 'unblockself', true );
409 $this->setGroupPermissions( 'user', 'block', true );
410 // Getting errors about creating users in db in provider.
411 // Need to use mutable to ensure different named testusers.
412 $users = [
413 'u1' => TestUserRegistry::getMutableTestUser( __CLASS__, 'sysop' )->getUser(),
414 'u2' => TestUserRegistry::getMutableTestUser( __CLASS__, 'sysop' )->getUser(),
415 'u3' => TestUserRegistry::getMutableTestUser( __CLASS__, 'sysop' )->getUser(),
416 'u4' => TestUserRegistry::getMutableTestUser( __CLASS__, 'sysop' )->getUser(),
417 'nonsysop' => $this->getTestUser()->getUser()
418 ];
419 foreach ( [ 'blockedUser', 'blockPerformer', 'adjustPerformer', 'adjustTarget' ] as $var ) {
420 $$var = $users[$$var];
421 }
422
423 $block = new \Block( [
424 'address' => $blockedUser->getName(),
425 'user' => $blockedUser->getId(),
426 'by' => $blockPerformer->getId(),
427 'expiry' => 'infinity',
428 'sitewide' => 1,
429 'enableAutoblock' => true,
430 ] );
431
432 $block->insert();
433
434 $this->assertSame(
435 SpecialBlock::checkUnblockSelf( $adjustTarget, $adjustPerformer ),
436 $expectedResult,
437 $reason
438 );
439 }
440
441 public function provideCheckUnblockSelf() {
442 // 'blockedUser', 'blockPerformer', 'adjustPerformer', 'adjustTarget'
443 return [
444 [ 'u1', 'u2', 'u3', 'u4', true, 'Unrelated users' ],
445 [ 'u1', 'u2', 'u1', 'u4', 'ipbblocked', 'Block unrelated while blocked' ],
446 [ 'u1', 'u2', 'u1', 'u1', true, 'Has unblockself' ],
447 [ 'nonsysop', 'u2', 'nonsysop', 'nonsysop', 'ipbnounblockself', 'no unblockself' ],
448 [ 'nonsysop', 'nonsysop', 'nonsysop', 'nonsysop', true, 'no unblockself but can de-selfblock' ],
449 [ 'u1', 'u2', 'u1', 'u2', true, 'Can block user who blocked' ],
450 ];
451 }
452
453 protected function insertBlock() {
454 $badActor = $this->getTestUser()->getUser();
455 $sysop = $this->getTestSysop()->getUser();
456
457 $block = new \Block( [
458 'address' => $badActor->getName(),
459 'user' => $badActor->getId(),
460 'by' => $sysop->getId(),
461 'expiry' => 'infinity',
462 'sitewide' => 1,
463 'enableAutoblock' => true,
464 ] );
465
466 $block->insert();
467
468 return $block;
469 }
470
471 protected function resetTables() {
472 $this->db->delete( 'ipblocks', '*', __METHOD__ );
473 $this->db->delete( 'ipblocks_restrictions', '*', __METHOD__ );
474 }
475
476 /**
477 * Get a BlockRestrictionStore instance
478 *
479 * @return BlockRestrictionStore
480 */
481 private function getBlockRestrictionStore() : BlockRestrictionStore {
482 $loadBalancer = $this->getMockBuilder( LoadBalancer::class )
483 ->disableOriginalConstructor()
484 ->getMock();
485
486 return new BlockRestrictionStore( $loadBalancer );
487 }
488 }