Merge "Fix use of GenderCache in ApiPageSet::processTitlesArray"
[lhc/web/wiklou.git] / tests / phpunit / includes / block / CompositeBlockTest.php
1 <?php
2
3 use MediaWiki\Block\BlockRestrictionStore;
4 use MediaWiki\Block\CompositeBlock;
5 use MediaWiki\Block\DatabaseBlock;
6 use MediaWiki\Block\Restriction\PageRestriction;
7 use MediaWiki\Block\Restriction\NamespaceRestriction;
8 use MediaWiki\Block\SystemBlock;
9 use MediaWiki\MediaWikiServices;
10
11 /**
12 * @group Database
13 * @group Blocking
14 * @coversDefaultClass \MediaWiki\Block\CompositeBlock
15 */
16 class CompositeBlockTest extends MediaWikiLangTestCase {
17 private function getPartialBlocks() {
18 $sysopId = $this->getTestSysop()->getUser()->getId();
19
20 $userBlock = new DatabaseBlock( [
21 'address' => $this->getTestUser()->getUser(),
22 'by' => $sysopId,
23 'sitewide' => false,
24 ] );
25 $ipBlock = new DatabaseBlock( [
26 'address' => '127.0.0.1',
27 'by' => $sysopId,
28 'sitewide' => false,
29 ] );
30
31 $userBlock->insert();
32 $ipBlock->insert();
33
34 return [
35 'user' => $userBlock,
36 'ip' => $ipBlock,
37 ];
38 }
39
40 private function deleteBlocks( $blocks ) {
41 foreach ( $blocks as $block ) {
42 $block->delete();
43 }
44 }
45
46 /**
47 * @covers ::__construct
48 * @dataProvider provideTestStrictestParametersApplied
49 */
50 public function testStrictestParametersApplied( $blocks, $expected ) {
51 $this->setMwGlobals( [
52 'wgBlockDisablesLogin' => false,
53 'wgBlockAllowsUTEdit' => true,
54 ] );
55
56 $block = new CompositeBlock( [
57 'originalBlocks' => $blocks,
58 ] );
59
60 $this->assertSame( $expected[ 'hideName' ], $block->getHideName() );
61 $this->assertSame( $expected[ 'sitewide' ], $block->isSitewide() );
62 $this->assertSame( $expected[ 'blockEmail' ], $block->isEmailBlocked() );
63 $this->assertSame( $expected[ 'allowUsertalk' ], $block->isUsertalkEditAllowed() );
64 }
65
66 public static function provideTestStrictestParametersApplied() {
67 return [
68 'Sitewide block and partial block' => [
69 [
70 new DatabaseBlock( [
71 'sitewide' => false,
72 'blockEmail' => true,
73 'allowUsertalk' => true,
74 ] ),
75 new DatabaseBlock( [
76 'sitewide' => true,
77 'blockEmail' => false,
78 'allowUsertalk' => false,
79 ] ),
80 ],
81 [
82 'hideName' => false,
83 'sitewide' => true,
84 'blockEmail' => true,
85 'allowUsertalk' => false,
86 ],
87 ],
88 'Partial block and system block' => [
89 [
90 new DatabaseBlock( [
91 'sitewide' => false,
92 'blockEmail' => true,
93 'allowUsertalk' => false,
94 ] ),
95 new SystemBlock( [
96 'systemBlock' => 'proxy',
97 ] ),
98 ],
99 [
100 'hideName' => false,
101 'sitewide' => true,
102 'blockEmail' => true,
103 'allowUsertalk' => false,
104 ],
105 ],
106 'System block and user name hiding block' => [
107 [
108 new DatabaseBlock( [
109 'hideName' => true,
110 'sitewide' => true,
111 'blockEmail' => true,
112 'allowUsertalk' => false,
113 ] ),
114 new SystemBlock( [
115 'systemBlock' => 'proxy',
116 ] ),
117 ],
118 [
119 'hideName' => true,
120 'sitewide' => true,
121 'blockEmail' => true,
122 'allowUsertalk' => false,
123 ],
124 ],
125 'Two lenient partial blocks' => [
126 [
127 new DatabaseBlock( [
128 'sitewide' => false,
129 'blockEmail' => false,
130 'allowUsertalk' => true,
131 ] ),
132 new DatabaseBlock( [
133 'sitewide' => false,
134 'blockEmail' => false,
135 'allowUsertalk' => true,
136 ] ),
137 ],
138 [
139 'hideName' => false,
140 'sitewide' => false,
141 'blockEmail' => false,
142 'allowUsertalk' => true,
143 ],
144 ],
145 ];
146 }
147
148 /**
149 * @covers ::appliesToTitle
150 */
151 public function testBlockAppliesToTitle() {
152 $this->setMwGlobals( [
153 'wgBlockDisablesLogin' => false,
154 ] );
155
156 $blocks = $this->getPartialBlocks();
157
158 $block = new CompositeBlock( [
159 'originalBlocks' => $blocks,
160 ] );
161
162 $pageFoo = $this->getExistingTestPage( 'Foo' );
163 $pageBar = $this->getExistingTestPage( 'User:Bar' );
164
165 $this->getBlockRestrictionStore()->insert( [
166 new PageRestriction( $blocks[ 'user' ]->getId(), $pageFoo->getId() ),
167 new NamespaceRestriction( $blocks[ 'ip' ]->getId(), NS_USER ),
168 ] );
169
170 $this->assertTrue( $block->appliesToTitle( $pageFoo->getTitle() ) );
171 $this->assertTrue( $block->appliesToTitle( $pageBar->getTitle() ) );
172
173 $this->deleteBlocks( $blocks );
174 }
175
176 /**
177 * @covers ::appliesToUsertalk
178 * @covers ::appliesToPage
179 * @covers ::appliesToNamespace
180 */
181 public function testBlockAppliesToUsertalk() {
182 $this->setMwGlobals( [
183 'wgBlockAllowsUTEdit' => true,
184 'wgBlockDisablesLogin' => false,
185 ] );
186
187 $blocks = $this->getPartialBlocks();
188
189 $block = new CompositeBlock( [
190 'originalBlocks' => $blocks,
191 ] );
192
193 $title = $blocks[ 'user' ]->getTarget()->getTalkPage();
194 $page = $this->getExistingTestPage( 'User talk:' . $title->getText() );
195
196 $this->getBlockRestrictionStore()->insert( [
197 new PageRestriction( $blocks[ 'user' ]->getId(), $page->getId() ),
198 new NamespaceRestriction( $blocks[ 'ip' ]->getId(), NS_USER ),
199 ] );
200
201 $this->assertTrue( $block->appliesToUsertalk( $blocks[ 'user' ]->getTarget()->getTalkPage() ) );
202
203 $this->deleteBlocks( $blocks );
204 }
205
206 /**
207 * @covers ::appliesToRight
208 * @dataProvider provideTestBlockAppliesToRight
209 */
210 public function testBlockAppliesToRight( $applies, $expected ) {
211 $this->setMwGlobals( [
212 'wgBlockDisablesLogin' => false,
213 ] );
214
215 $block = new CompositeBlock( [
216 'originalBlocks' => [
217 $this->getMockBlockForTestAppliesToRight( $applies[ 0 ] ),
218 $this->getMockBlockForTestAppliesToRight( $applies[ 1 ] ),
219 ],
220 ] );
221
222 $this->assertSame( $block->appliesToRight( 'right' ), $expected );
223 }
224
225 private function getMockBlockForTestAppliesToRight( $applies ) {
226 $mockBlock = $this->getMockBuilder( DatabaseBlock::class )
227 ->setMethods( [ 'appliesToRight' ] )
228 ->getMock();
229 $mockBlock->method( 'appliesToRight' )
230 ->willReturn( $applies );
231 return $mockBlock;
232 }
233
234 public function provideTestBlockAppliesToRight() {
235 return [
236 'Block does not apply if no original blocks apply' => [
237 [ false, false ],
238 false,
239 ],
240 'Block applies if any original block applies (second block doesn\'t apply)' => [
241 [ true, false ],
242 true,
243 ],
244 'Block applies if any original block applies (second block unsure)' => [
245 [ true, null ],
246 true,
247 ],
248 'Block is unsure if all original blocks are unsure' => [
249 [ null, null ],
250 null,
251 ],
252 'Block is unsure if any original block is unsure, and no others apply' => [
253 [ null, false ],
254 null,
255 ],
256 ];
257 }
258
259 /**
260 * @covers ::getPermissionsError
261 * @dataProvider provideGetPermissionsError
262 */
263 public function testGetPermissionsError( $ids, $expectedIdsMsg ) {
264 // Some block options
265 $timestamp = time();
266 $target = '1.2.3.4';
267 $byText = 'MediaWiki default';
268 $formattedByText = "\u{202A}{$byText}\u{202C}";
269 $reason = '';
270 $expiry = 'infinite';
271
272 $block = $this->getMockBuilder( CompositeBlock::class )
273 ->setMethods( [ 'getIds', 'getBlockErrorParams' ] )
274 ->getMock();
275 $block->method( 'getIds' )
276 ->willReturn( $ids );
277 $block->method( 'getBlockErrorParams' )
278 ->willReturn( [
279 $formattedByText,
280 $reason,
281 $target,
282 $formattedByText,
283 null,
284 $timestamp,
285 $target,
286 $expiry,
287 ] );
288
289 $this->assertSame( [
290 'blockedtext-composite',
291 $formattedByText,
292 $reason,
293 $target,
294 $formattedByText,
295 $expectedIdsMsg,
296 $timestamp,
297 $target,
298 $expiry,
299 ], $block->getPermissionsError( RequestContext::getMain() ) );
300 }
301
302 public static function provideGetPermissionsError() {
303 return [
304 'All original blocks are system blocks' => [
305 [],
306 'Your IP address appears in multiple blacklists',
307 ],
308 'One original block is a database block' => [
309 [ 100 ],
310 'Relevant block IDs: #100 (your IP address may also be blacklisted)',
311 ],
312 'Several original blocks are database blocks' => [
313 [ 100, 101, 102 ],
314 'Relevant block IDs: #100, #101, #102 (your IP address may also be blacklisted)',
315 ],
316 ];
317 }
318
319 /**
320 * Get an instance of BlockRestrictionStore
321 *
322 * @return BlockRestrictionStore
323 */
324 protected function getBlockRestrictionStore() : BlockRestrictionStore {
325 return MediaWikiServices::getInstance()->getBlockRestrictionStore();
326 }
327 }