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