1<?php
2
3/**
4 * @covers ProtectLogFormatter
5 */
6class ProtectLogFormatterTest extends LogFormatterTestCase {
7
8	/**
9	 * Provide different rows from the logging table to test
10	 * for backward compatibility.
11	 * Do not change the existing data, just add a new database row
12	 */
13	public static function provideProtectLogDatabaseRows() {
14		return [
15			// Current format
16			[
17				[
18					'type' => 'protect',
19					'action' => 'protect',
20					'comment' => 'protect comment',
21					'namespace' => NS_MAIN,
22					'title' => 'ProtectPage',
23					'params' => [
24						'4::description' => '[edit=sysop] (indefinite)[move=sysop] (indefinite)',
25						'5:bool:cascade' => false,
26						'details' => [
27							[
28								'type' => 'edit',
29								'level' => 'sysop',
30								'expiry' => 'infinity',
31								'cascade' => false,
32							],
33							[
34								'type' => 'move',
35								'level' => 'sysop',
36								'expiry' => 'infinity',
37								'cascade' => false,
38							],
39						],
40					],
41				],
42				[
43					'text' => 'User protected ProtectPage [Edit=Allow only administrators] ' .
44						'(indefinite) [Move=Allow only administrators] (indefinite)',
45					'api' => [
46						'description' => '[edit=sysop] (indefinite)[move=sysop] (indefinite)',
47						'cascade' => false,
48						'details' => [
49							[
50								'type' => 'edit',
51								'level' => 'sysop',
52								'expiry' => 'infinite',
53								'cascade' => false,
54							],
55							[
56								'type' => 'move',
57								'level' => 'sysop',
58								'expiry' => 'infinite',
59								'cascade' => false,
60							],
61						],
62					],
63				],
64			],
65
66			// Current format with cascade
67			[
68				[
69					'type' => 'protect',
70					'action' => 'protect',
71					'comment' => 'protect comment',
72					'namespace' => NS_MAIN,
73					'title' => 'ProtectPage',
74					'params' => [
75						'4::description' => '[edit=sysop] (indefinite)[move=sysop] (indefinite)',
76						'5:bool:cascade' => true,
77						'details' => [
78							[
79								'type' => 'edit',
80								'level' => 'sysop',
81								'expiry' => 'infinity',
82								'cascade' => true,
83							],
84							[
85								'type' => 'move',
86								'level' => 'sysop',
87								'expiry' => 'infinity',
88								'cascade' => false,
89							],
90						],
91					],
92				],
93				[
94					'text' => 'User protected ProtectPage [Edit=Allow only administrators] ' .
95						'(indefinite) [Move=Allow only administrators] (indefinite) [cascading]',
96					'api' => [
97						'description' => '[edit=sysop] (indefinite)[move=sysop] (indefinite)',
98						'cascade' => true,
99						'details' => [
100							[
101								'type' => 'edit',
102								'level' => 'sysop',
103								'expiry' => 'infinite',
104								'cascade' => true,
105							],
106							[
107								'type' => 'move',
108								'level' => 'sysop',
109								'expiry' => 'infinite',
110								'cascade' => false,
111							],
112						],
113					],
114				],
115			],
116
117			// Legacy format
118			[
119				[
120					'type' => 'protect',
121					'action' => 'protect',
122					'comment' => 'protect comment',
123					'namespace' => NS_MAIN,
124					'title' => 'ProtectPage',
125					'params' => [
126						'[edit=sysop] (indefinite)[move=sysop] (indefinite)',
127						'',
128					],
129				],
130				[
131					'legacy' => true,
132					'text' => 'User protected ProtectPage [edit=sysop] (indefinite)[move=sysop] (indefinite)',
133					'api' => [
134						'description' => '[edit=sysop] (indefinite)[move=sysop] (indefinite)',
135						'cascade' => false,
136					],
137				],
138			],
139
140			// Legacy format with cascade
141			[
142				[
143					'type' => 'protect',
144					'action' => 'protect',
145					'comment' => 'protect comment',
146					'namespace' => NS_MAIN,
147					'title' => 'ProtectPage',
148					'params' => [
149						'[edit=sysop] (indefinite)[move=sysop] (indefinite)',
150						'cascade',
151					],
152				],
153				[
154					'legacy' => true,
155					'text' => 'User protected ProtectPage [edit=sysop] ' .
156						'(indefinite)[move=sysop] (indefinite) [cascading]',
157					'api' => [
158						'description' => '[edit=sysop] (indefinite)[move=sysop] (indefinite)',
159						'cascade' => true,
160					],
161				],
162			],
163		];
164	}
165
166	/**
167	 * @dataProvider provideProtectLogDatabaseRows
168	 */
169	public function testProtectLogDatabaseRows( $row, $extra ) {
170		$this->doTestLogFormatter( $row, $extra );
171	}
172
173	/**
174	 * Provide different rows from the logging table to test
175	 * for backward compatibility.
176	 * Do not change the existing data, just add a new database row
177	 */
178	public static function provideModifyLogDatabaseRows() {
179		return [
180			// Current format
181			[
182				[
183					'type' => 'protect',
184					'action' => 'modify',
185					'comment' => 'protect comment',
186					'namespace' => NS_MAIN,
187					'title' => 'ProtectPage',
188					'params' => [
189						'4::description' => '[edit=sysop] (indefinite)[move=sysop] (indefinite)',
190						'5:bool:cascade' => false,
191						'details' => [
192							[
193								'type' => 'edit',
194								'level' => 'sysop',
195								'expiry' => 'infinity',
196								'cascade' => false,
197							],
198							[
199								'type' => 'move',
200								'level' => 'sysop',
201								'expiry' => 'infinity',
202								'cascade' => false,
203							],
204						],
205					],
206				],
207				[
208					'text' => 'User changed protection settings for ProtectPage ' .
209						'[Edit=Allow only administrators] ' .
210						'(indefinite) [Move=Allow only administrators] (indefinite)',
211					'api' => [
212						'description' => '[edit=sysop] (indefinite)[move=sysop] (indefinite)',
213						'cascade' => false,
214						'details' => [
215							[
216								'type' => 'edit',
217								'level' => 'sysop',
218								'expiry' => 'infinite',
219								'cascade' => false,
220							],
221							[
222								'type' => 'move',
223								'level' => 'sysop',
224								'expiry' => 'infinite',
225								'cascade' => false,
226							],
227						],
228					],
229				],
230			],
231
232			// Current format with cascade
233			[
234				[
235					'type' => 'protect',
236					'action' => 'modify',
237					'comment' => 'protect comment',
238					'namespace' => NS_MAIN,
239					'title' => 'ProtectPage',
240					'params' => [
241						'4::description' => '[edit=sysop] (indefinite)[move=sysop] (indefinite)',
242						'5:bool:cascade' => true,
243						'details' => [
244							[
245								'type' => 'edit',
246								'level' => 'sysop',
247								'expiry' => 'infinity',
248								'cascade' => true,
249							],
250							[
251								'type' => 'move',
252								'level' => 'sysop',
253								'expiry' => 'infinity',
254								'cascade' => false,
255							],
256						],
257					],
258				],
259				[
260					'text' => 'User changed protection settings for ProtectPage ' .
261						'[Edit=Allow only administrators] (indefinite) ' .
262						'[Move=Allow only administrators] (indefinite) [cascading]',
263					'api' => [
264						'description' => '[edit=sysop] (indefinite)[move=sysop] (indefinite)',
265						'cascade' => true,
266						'details' => [
267							[
268								'type' => 'edit',
269								'level' => 'sysop',
270								'expiry' => 'infinite',
271								'cascade' => true,
272							],
273							[
274								'type' => 'move',
275								'level' => 'sysop',
276								'expiry' => 'infinite',
277								'cascade' => false,
278							],
279						],
280					],
281				],
282			],
283
284			// Legacy format
285			[
286				[
287					'type' => 'protect',
288					'action' => 'modify',
289					'comment' => 'protect comment',
290					'namespace' => NS_MAIN,
291					'title' => 'ProtectPage',
292					'params' => [
293						'[edit=sysop] (indefinite)[move=sysop] (indefinite)',
294						'',
295					],
296				],
297				[
298					'legacy' => true,
299					'text' => 'User changed protection settings for ProtectPage ' .
300						'[edit=sysop] (indefinite)[move=sysop] (indefinite)',
301					'api' => [
302						'description' => '[edit=sysop] (indefinite)[move=sysop] (indefinite)',
303						'cascade' => false,
304					],
305				],
306			],
307
308			// Legacy format with cascade
309			[
310				[
311					'type' => 'protect',
312					'action' => 'modify',
313					'comment' => 'protect comment',
314					'namespace' => NS_MAIN,
315					'title' => 'ProtectPage',
316					'params' => [
317						'[edit=sysop] (indefinite)[move=sysop] (indefinite)',
318						'cascade',
319					],
320				],
321				[
322					'legacy' => true,
323					'text' => 'User changed protection settings for ProtectPage ' .
324						'[edit=sysop] (indefinite)[move=sysop] (indefinite) [cascading]',
325					'api' => [
326						'description' => '[edit=sysop] (indefinite)[move=sysop] (indefinite)',
327						'cascade' => true,
328					],
329				],
330			],
331		];
332	}
333
334	/**
335	 * @dataProvider provideModifyLogDatabaseRows
336	 */
337	public function testModifyLogDatabaseRows( $row, $extra ) {
338		$this->doTestLogFormatter( $row, $extra );
339	}
340
341	/**
342	 * Provide different rows from the logging table to test
343	 * for backward compatibility.
344	 * Do not change the existing data, just add a new database row
345	 */
346	public static function provideUnprotectLogDatabaseRows() {
347		return [
348			// Current format
349			[
350				[
351					'type' => 'protect',
352					'action' => 'unprotect',
353					'comment' => 'unprotect comment',
354					'namespace' => NS_MAIN,
355					'title' => 'ProtectPage',
356					'params' => [],
357				],
358				[
359					'text' => 'User removed protection from ProtectPage',
360					'api' => [],
361				],
362			],
363		];
364	}
365
366	/**
367	 * @dataProvider provideUnprotectLogDatabaseRows
368	 */
369	public function testUnprotectLogDatabaseRows( $row, $extra ) {
370		$this->doTestLogFormatter( $row, $extra );
371	}
372
373	/**
374	 * Provide different rows from the logging table to test
375	 * for backward compatibility.
376	 * Do not change the existing data, just add a new database row
377	 */
378	public static function provideMoveProtLogDatabaseRows() {
379		return [
380			// Current format
381			[
382				[
383					'type' => 'protect',
384					'action' => 'move_prot',
385					'comment' => 'Move comment',
386					'namespace' => NS_MAIN,
387					'title' => 'NewPage',
388					'params' => [
389						'4::oldtitle' => 'OldPage',
390					],
391				],
392				[
393					'text' => 'User moved protection settings from OldPage to NewPage',
394					'api' => [
395						'oldtitle_ns' => 0,
396						'oldtitle_title' => 'OldPage',
397					],
398				],
399			],
400
401			// Legacy format
402			[
403				[
404					'type' => 'protect',
405					'action' => 'move_prot',
406					'comment' => 'Move comment',
407					'namespace' => NS_MAIN,
408					'title' => 'NewPage',
409					'params' => [
410						'OldPage',
411					],
412				],
413				[
414					'legacy' => true,
415					'text' => 'User moved protection settings from OldPage to NewPage',
416					'api' => [
417						'oldtitle_ns' => 0,
418						'oldtitle_title' => 'OldPage',
419					],
420				],
421			],
422		];
423	}
424
425	/**
426	 * @dataProvider provideMoveProtLogDatabaseRows
427	 */
428	public function testMoveProtLogDatabaseRows( $row, $extra ) {
429		$this->doTestLogFormatter( $row, $extra );
430	}
431
432	public function provideGetActionLinks() {
433		yield [
434			[ 'protect' ],
435			true
436		];
437		yield [
438			[],
439			false
440		];
441	}
442
443	/**
444	 * @param string[] $permissions
445	 * @param bool $shouldMatch
446	 * @dataProvider provideGetActionLinks
447	 * @covers ProtectLogFormatter::getActionLinks
448	 */
449	public function testGetActionLinks( array $permissions, $shouldMatch ) {
450		RequestContext::resetMain();
451		$user = $this->getTestUser()->getUser();
452		$this->overrideUserPermissions( $user, $permissions );
453		$row = $this->expandDatabaseRow( [
454			'type' => 'protect',
455			'action' => 'unprotect',
456			'comment' => 'unprotect comment',
457			'namespace' => NS_MAIN,
458			'title' => 'ProtectPage',
459			'params' => [],
460		], false );
461		$context = new RequestContext();
462		$context->setUser( $user );
463		$formatter = LogFormatter::newFromRow( $row );
464		$formatter->setContext( $context );
465		if ( $shouldMatch ) {
466			$this->assertStringMatchesFormat(
467				'%Aaction=protect%A', $formatter->getActionLinks() );
468		} else {
469			$this->assertStringNotMatchesFormat(
470				'%Aaction=protect%A', $formatter->getActionLinks() );
471		}
472	}
473}
474