3 use MediaWiki\Cache\LinkCache
;
4 use MediaWiki\Context\RequestContext
;
5 use MediaWiki\Linker\LinkRendererFactory
;
6 use MediaWiki\Tests\Unit\Permissions\MockAuthorityTrait
;
7 use MediaWiki\Title\Title
;
8 use MediaWiki\Title\TitleFactory
;
9 use MediaWiki\User\UserIdentityValue
;
10 use Wikimedia\Rdbms\IDatabase
;
11 use Wikimedia\Rdbms\LBFactory
;
14 * @covers \ProtectLogFormatter
16 class ProtectLogFormatterTest
extends LogFormatterTestCase
{
18 use MockAuthorityTrait
;
20 protected function setUp(): void
{
23 $db = $this->createNoOpMock( IDatabase
::class, [ 'getInfinity' ] );
24 $db->method( 'getInfinity' )->willReturn( 'infinity' );
25 $lbFactory = $this->createMock( LBFactory
::class );
26 $lbFactory->method( 'getReplicaDatabase' )->willReturn( $db );
27 $this->setService( 'DBLoadBalancerFactory', $lbFactory );
31 * Provide different rows from the logging table to test
32 * for backward compatibility.
33 * Do not change the existing data, just add a new database row
35 public static function provideProtectLogDatabaseRows() {
41 'action' => 'protect',
42 'comment' => 'protect comment',
43 'namespace' => NS_MAIN
,
44 'title' => 'ProtectPage',
46 '4::description' => '[edit=sysop] (indefinite)[move=sysop] (indefinite)',
47 '5:bool:cascade' => false,
52 'expiry' => 'infinity',
58 'expiry' => 'infinity',
65 'text' => 'User protected ProtectPage [Edit=Allow only administrators] ' .
66 '(indefinite) [Move=Allow only administrators] (indefinite)',
68 'description' => '[edit=sysop] (indefinite)[move=sysop] (indefinite)',
74 'expiry' => 'infinite',
80 'expiry' => 'infinite',
88 // Current format with cascade
92 'action' => 'protect',
93 'comment' => 'protect comment',
94 'namespace' => NS_MAIN
,
95 'title' => 'ProtectPage',
97 '4::description' => '[edit=sysop] (indefinite)[move=sysop] (indefinite)',
98 '5:bool:cascade' => true,
103 'expiry' => 'infinity',
109 'expiry' => 'infinity',
116 'text' => 'User protected ProtectPage [Edit=Allow only administrators] ' .
117 '(indefinite) [Move=Allow only administrators] (indefinite) [cascading]',
119 'description' => '[edit=sysop] (indefinite)[move=sysop] (indefinite)',
125 'expiry' => 'infinite',
131 'expiry' => 'infinite',
143 'action' => 'protect',
144 'comment' => 'protect comment',
145 'namespace' => NS_MAIN
,
146 'title' => 'ProtectPage',
148 '[edit=sysop] (indefinite)[move=sysop] (indefinite)',
154 'text' => 'User protected ProtectPage [edit=sysop] (indefinite)[move=sysop] (indefinite)',
156 'description' => '[edit=sysop] (indefinite)[move=sysop] (indefinite)',
162 // Legacy format with cascade
166 'action' => 'protect',
167 'comment' => 'protect comment',
168 'namespace' => NS_MAIN
,
169 'title' => 'ProtectPage',
171 '[edit=sysop] (indefinite)[move=sysop] (indefinite)',
177 'text' => 'User protected ProtectPage [edit=sysop] ' .
178 '(indefinite)[move=sysop] (indefinite) [cascading]',
180 'description' => '[edit=sysop] (indefinite)[move=sysop] (indefinite)',
189 * @dataProvider provideProtectLogDatabaseRows
191 public function testProtectLogDatabaseRows( $row, $extra ) {
192 $this->doTestLogFormatter( $row, $extra );
196 * Provide different rows from the logging table to test
197 * for backward compatibility.
198 * Do not change the existing data, just add a new database row
200 public static function provideModifyLogDatabaseRows() {
206 'action' => 'modify',
207 'comment' => 'protect comment',
208 'namespace' => NS_MAIN
,
209 'title' => 'ProtectPage',
211 '4::description' => '[edit=sysop] (indefinite)[move=sysop] (indefinite)',
212 '5:bool:cascade' => false,
217 'expiry' => 'infinity',
223 'expiry' => 'infinity',
230 'text' => 'User changed protection settings for ProtectPage ' .
231 '[Edit=Allow only administrators] ' .
232 '(indefinite) [Move=Allow only administrators] (indefinite)',
234 'description' => '[edit=sysop] (indefinite)[move=sysop] (indefinite)',
240 'expiry' => 'infinite',
246 'expiry' => 'infinite',
254 // Current format with cascade
258 'action' => 'modify',
259 'comment' => 'protect comment',
260 'namespace' => NS_MAIN
,
261 'title' => 'ProtectPage',
263 '4::description' => '[edit=sysop] (indefinite)[move=sysop] (indefinite)',
264 '5:bool:cascade' => true,
269 'expiry' => 'infinity',
275 'expiry' => 'infinity',
282 'text' => 'User changed protection settings for ProtectPage ' .
283 '[Edit=Allow only administrators] (indefinite) ' .
284 '[Move=Allow only administrators] (indefinite) [cascading]',
286 'description' => '[edit=sysop] (indefinite)[move=sysop] (indefinite)',
292 'expiry' => 'infinite',
298 'expiry' => 'infinite',
310 'action' => 'modify',
311 'comment' => 'protect comment',
312 'namespace' => NS_MAIN
,
313 'title' => 'ProtectPage',
315 '[edit=sysop] (indefinite)[move=sysop] (indefinite)',
321 'text' => 'User changed protection settings for ProtectPage ' .
322 '[edit=sysop] (indefinite)[move=sysop] (indefinite)',
324 'description' => '[edit=sysop] (indefinite)[move=sysop] (indefinite)',
330 // Legacy format with cascade
334 'action' => 'modify',
335 'comment' => 'protect comment',
336 'namespace' => NS_MAIN
,
337 'title' => 'ProtectPage',
339 '[edit=sysop] (indefinite)[move=sysop] (indefinite)',
345 'text' => 'User changed protection settings for ProtectPage ' .
346 '[edit=sysop] (indefinite)[move=sysop] (indefinite) [cascading]',
348 'description' => '[edit=sysop] (indefinite)[move=sysop] (indefinite)',
357 * @dataProvider provideModifyLogDatabaseRows
359 public function testModifyLogDatabaseRows( $row, $extra ) {
360 $this->doTestLogFormatter( $row, $extra );
364 * Provide different rows from the logging table to test
365 * for backward compatibility.
366 * Do not change the existing data, just add a new database row
368 public static function provideUnprotectLogDatabaseRows() {
374 'action' => 'unprotect',
375 'comment' => 'unprotect comment',
376 'namespace' => NS_MAIN
,
377 'title' => 'ProtectPage',
381 'text' => 'User removed protection from ProtectPage',
389 * @dataProvider provideUnprotectLogDatabaseRows
391 public function testUnprotectLogDatabaseRows( $row, $extra ) {
392 $this->doTestLogFormatter( $row, $extra );
396 * Provide different rows from the logging table to test
397 * for backward compatibility.
398 * Do not change the existing data, just add a new database row
400 public static function provideMoveProtLogDatabaseRows() {
406 'action' => 'move_prot',
407 'comment' => 'Move comment',
408 'namespace' => NS_MAIN
,
409 'title' => 'NewPage',
411 '4::oldtitle' => 'OldPage',
415 'text' => 'User moved protection settings from OldPage to NewPage',
418 'oldtitle_title' => 'OldPage',
427 'action' => 'move_prot',
428 'comment' => 'Move comment',
429 'namespace' => NS_MAIN
,
430 'title' => 'NewPage',
437 'text' => 'User moved protection settings from OldPage to NewPage',
440 'oldtitle_title' => 'OldPage',
448 * @dataProvider provideMoveProtLogDatabaseRows
450 public function testMoveProtLogDatabaseRows( $row, $extra ) {
451 $this->doTestLogFormatter( $row, $extra );
454 public static function provideGetActionLinks() {
466 * @param string[] $permissions
467 * @param bool $shouldMatch
468 * @dataProvider provideGetActionLinks
469 * @covers \ProtectLogFormatter::getActionLinks
471 public function testGetActionLinks( array $permissions, $shouldMatch ) {
472 RequestContext
::resetMain();
473 $user = $this->mockUserAuthorityWithPermissions( new UserIdentityValue( 42, __METHOD__
), $permissions );
474 $row = $this->expandDatabaseRow( [
476 'action' => 'unprotect',
477 'comment' => 'unprotect comment',
478 'namespace' => NS_MAIN
,
479 'title' => 'ProtectPage',
482 $context = new RequestContext();
483 $context->setAuthority( $user );
484 $context->setLanguage( 'en' );
485 $formatter = $this->getServiceContainer()->getLogFormatterFactory()->newFromRow( $row );
486 $formatter->setContext( $context );
487 $titleFactory = $this->createMock( TitleFactory
::class );
488 $titleFactory->method( 'makeTitle' )->willReturnCallback( static function ( ...$params ) {
489 $ret = Title
::makeTitle( ...$params );
490 $ret->resetArticleID( 0 );
493 $this->setService( 'TitleFactory', $titleFactory );
494 $formatter->setLinkRenderer( ( new LinkRendererFactory(
495 $this->getServiceContainer()->getTitleFormatter(),
496 $this->createMock( LinkCache
::class ),
497 $this->getServiceContainer()->getSpecialPageFactory(),
498 $this->getServiceContainer()->getHookContainer()
500 if ( $shouldMatch ) {
501 $this->assertStringMatchesFormat(
502 '%Aaction=protect%A', $formatter->getActionLinks() );
504 $this->assertStringNotMatchesFormat(
505 '%Aaction=protect%A', $formatter->getActionLinks() );