2020-01-13 13:07:34 +00:00
|
|
|
<?php
|
|
|
|
|
2018-08-28 17:22:16 +00:00
|
|
|
use MediaWiki\Extension\AbuseFilter\AbuseFilterServices;
|
2021-01-14 16:18:13 +00:00
|
|
|
use MediaWiki\Extension\AbuseFilter\Variables\LazyLoadedVariable;
|
2021-01-02 14:01:00 +00:00
|
|
|
use MediaWiki\Extension\AbuseFilter\Variables\VariableHolder;
|
2022-07-02 12:45:19 +00:00
|
|
|
use MediaWiki\Permissions\UltimateAuthority;
|
|
|
|
use MediaWiki\User\UserIdentityValue;
|
2020-01-13 13:07:34 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @group Test
|
|
|
|
* @group AbuseFilter
|
|
|
|
* @group AbuseFilterGeneric
|
|
|
|
* @group Database
|
2021-01-08 17:17:41 +00:00
|
|
|
* @coversDefaultClass \MediaWiki\Extension\AbuseFilter\Variables\LazyVariableComputer
|
|
|
|
* @todo Move to LazyVariableComputerTest
|
2020-01-13 13:07:34 +00:00
|
|
|
*/
|
2021-01-08 17:17:41 +00:00
|
|
|
class LazyVariableComputerDBTest extends MediaWikiIntegrationTestCase {
|
2020-09-16 09:15:38 +00:00
|
|
|
|
2021-01-15 21:09:52 +00:00
|
|
|
/** @inheritDoc */
|
2020-01-13 13:07:34 +00:00
|
|
|
protected $tablesUsed = [
|
|
|
|
'page',
|
|
|
|
'text',
|
|
|
|
'page_restrictions',
|
|
|
|
'user',
|
2018-08-28 17:22:16 +00:00
|
|
|
'recentchanges',
|
2020-01-13 13:07:34 +00:00
|
|
|
];
|
|
|
|
|
2018-08-28 17:22:16 +00:00
|
|
|
/**
|
2020-01-13 13:07:34 +00:00
|
|
|
* @param string $oldText The old wikitext of the page
|
|
|
|
* @param string $newText The new wikitext of the page
|
|
|
|
* @param string $summary
|
|
|
|
* @param array $expected Expected edit vars
|
2021-01-08 17:17:41 +00:00
|
|
|
* @covers ::compute
|
|
|
|
* @dataProvider provideEditRelatedVars
|
2020-01-13 13:07:34 +00:00
|
|
|
*/
|
2021-01-08 17:17:41 +00:00
|
|
|
public function testEditRelatedVars( $oldText, $newText, $summary, array $expected ) {
|
2022-06-28 20:46:45 +00:00
|
|
|
$title = Title::makeTitle( NS_MAIN, 'TestEditRelatedVars' );
|
2021-12-16 22:51:24 +00:00
|
|
|
$page = $this->getServiceContainer()->getWikiPageFactory()->newFromTitle( $title );
|
2020-01-13 13:07:34 +00:00
|
|
|
|
2022-06-28 20:46:45 +00:00
|
|
|
$this->editPage( $page, $oldText, 'Creating the test page' );
|
|
|
|
$this->editPage( $page, $newText, $summary );
|
2020-01-13 13:07:34 +00:00
|
|
|
|
2021-01-02 14:01:00 +00:00
|
|
|
$baseVars = VariableHolder::newFromArray( [
|
2020-01-13 13:07:34 +00:00
|
|
|
'old_wikitext' => $oldText,
|
|
|
|
'new_wikitext' => $newText,
|
|
|
|
'summary' => $summary
|
|
|
|
] );
|
|
|
|
|
2021-01-03 13:10:20 +00:00
|
|
|
$generator = AbuseFilterServices::getVariableGeneratorFactory()->newGenerator( $baseVars );
|
2021-06-24 03:30:34 +00:00
|
|
|
$actualHolder = $generator->addEditVars( $page, $this->getTestUser()->getUser() )
|
2020-10-18 22:25:05 +00:00
|
|
|
->getVariableHolder();
|
|
|
|
$actual = AbuseFilterServices::getVariablesManager()->exportAllVars( $actualHolder );
|
2020-01-13 13:07:34 +00:00
|
|
|
|
|
|
|
// Special case for new_html: avoid flaky tests, and only check containment
|
|
|
|
$this->assertStringContainsString( '<div class="mw-parser-output', $actual['new_html'] );
|
2022-10-07 17:05:41 +00:00
|
|
|
$this->assertDoesNotMatchRegularExpression( "/<!--\s*NewPP limit/", $actual['new_html'] );
|
|
|
|
$this->assertDoesNotMatchRegularExpression( "/<!--\s*Transclusion/", $actual['new_html'] );
|
2020-01-13 13:07:34 +00:00
|
|
|
foreach ( $expected['new_html'] as $needle ) {
|
|
|
|
$this->assertStringContainsString( $needle, $actual['new_html'], 'Checking new_html' );
|
|
|
|
}
|
|
|
|
unset( $actual['new_html'], $expected['new_html'] );
|
|
|
|
|
|
|
|
$this->assertEquals( $expected, $actual );
|
|
|
|
}
|
|
|
|
|
2021-07-21 18:51:12 +00:00
|
|
|
public function provideEditRelatedVars(): Generator {
|
2020-01-13 13:07:34 +00:00
|
|
|
$summary = __METHOD__;
|
|
|
|
|
|
|
|
// phpcs:disable Generic.Files.LineLength
|
|
|
|
$old = '[https://a.com Test] foo';
|
|
|
|
$new = "'''Random'''.\nSome ''special'' chars: àèìòù 名探偵コナン.\n[[Help:PST|]] test, [//www.b.com link]";
|
|
|
|
$expected = [
|
|
|
|
'old_wikitext' => $old,
|
|
|
|
'new_wikitext' => $new,
|
|
|
|
'summary' => $summary,
|
|
|
|
'new_html' => [ '<p><b>Random</b>', '<i>special</i>', 'PST</a>', 'link</a>' ],
|
|
|
|
'new_pst' => "'''Random'''.\nSome ''special'' chars: àèìòù 名探偵コナン.\n[[Help:PST|PST]] test, [//www.b.com link]",
|
|
|
|
'new_text' => "Random.\nSome special chars: àèìòù 名探偵コナン.\nPST test, link",
|
|
|
|
'edit_diff' => "@@ -1,1 +1,3 @@\n-[https://a.com Test] foo\n+'''Random'''.\n+Some ''special'' chars: àèìòù 名探偵コナン.\n+[[Help:PST|]] test, [//www.b.com link]\n",
|
|
|
|
'edit_diff_pst' => "@@ -1,1 +1,3 @@\n-[https://a.com Test] foo\n+'''Random'''.\n+Some ''special'' chars: àèìòù 名探偵コナン.\n+[[Help:PST|PST]] test, [//www.b.com link]\n",
|
|
|
|
'new_size' => strlen( $new ),
|
|
|
|
'old_size' => strlen( $old ),
|
|
|
|
'edit_delta' => strlen( $new ) - strlen( $old ),
|
|
|
|
'added_lines' => explode( "\n", $new ),
|
|
|
|
'removed_lines' => [ $old ],
|
|
|
|
'added_lines_pst' => [ "'''Random'''.", "Some ''special'' chars: àèìòù 名探偵コナン.", '[[Help:PST|PST]] test, [//www.b.com link]' ],
|
|
|
|
'all_links' => [ '//www.b.com' ],
|
|
|
|
'old_links' => [ 'https://a.com' ],
|
|
|
|
'added_links' => [ '//www.b.com' ],
|
|
|
|
'removed_links' => [ 'https://a.com' ]
|
|
|
|
];
|
|
|
|
|
|
|
|
yield 'PST and special chars' => [ $old, $new, $summary, $expected ];
|
|
|
|
|
|
|
|
$old = "'''Random'''.\nSome ''special'' chars: àèìòù 名探偵コナン.\n[[Help:PST|]] test, [//www.b.com link]";
|
|
|
|
$new = '[https://a.com Test] foo';
|
|
|
|
$expected = [
|
|
|
|
'old_wikitext' => $old,
|
|
|
|
'new_wikitext' => $new,
|
|
|
|
'summary' => $summary,
|
|
|
|
'new_html' => [ 'Test</a>' ],
|
|
|
|
'new_pst' => '[https://a.com Test] foo',
|
|
|
|
'new_text' => 'Test foo',
|
|
|
|
'edit_diff' => "@@ -1,3 +1,1 @@\n-'''Random'''.\n-Some ''special'' chars: àèìòù 名探偵コナン.\n-[[Help:PST|]] test, [//www.b.com link]\n+[https://a.com Test] foo\n",
|
|
|
|
'edit_diff_pst' => "@@ -1,3 +1,1 @@\n-'''Random'''.\n-Some ''special'' chars: àèìòù 名探偵コナン.\n-[[Help:PST|]] test, [//www.b.com link]\n+[https://a.com Test] foo\n",
|
|
|
|
'new_size' => strlen( $new ),
|
|
|
|
'old_size' => strlen( $old ),
|
|
|
|
'edit_delta' => strlen( $new ) - strlen( $old ),
|
|
|
|
'added_lines' => [ $new ],
|
|
|
|
'removed_lines' => explode( "\n", $old ),
|
|
|
|
'added_lines_pst' => [ $new ],
|
|
|
|
'all_links' => [ 'https://a.com' ],
|
|
|
|
'old_links' => [ '//www.b.com' ],
|
|
|
|
'added_links' => [ 'https://a.com' ],
|
|
|
|
'removed_links' => [ '//www.b.com' ]
|
|
|
|
];
|
|
|
|
|
|
|
|
yield 'PST and special chars, reverse' => [ $old, $new, $summary, $expected ];
|
|
|
|
// phpcs:enable Generic.Files.LineLength
|
|
|
|
|
|
|
|
$old = 'This edit will be pretty smal';
|
|
|
|
$new = $old . 'l';
|
|
|
|
|
|
|
|
$expected = [
|
|
|
|
'old_wikitext' => $old,
|
|
|
|
'new_wikitext' => $new,
|
|
|
|
'summary' => $summary,
|
|
|
|
'new_html' => [ "<p>This edit will be pretty small\n</p>" ],
|
|
|
|
'new_pst' => $new,
|
|
|
|
'new_text' => $new,
|
|
|
|
'edit_diff' => "@@ -1,1 +1,1 @@\n-$old\n+$new\n",
|
|
|
|
'edit_diff_pst' => "@@ -1,1 +1,1 @@\n-$old\n+$new\n",
|
|
|
|
'new_size' => strlen( $new ),
|
|
|
|
'old_size' => strlen( $old ),
|
|
|
|
'edit_delta' => 1,
|
|
|
|
'added_lines' => [ $new ],
|
|
|
|
'removed_lines' => [ $old ],
|
|
|
|
'added_lines_pst' => [ $new ],
|
|
|
|
'all_links' => [],
|
|
|
|
'old_links' => [],
|
|
|
|
'added_links' => [],
|
|
|
|
'removed_links' => []
|
|
|
|
];
|
|
|
|
|
|
|
|
yield 'Small edit' => [ $old, $new, $summary, $expected ];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Make different users edit a page, so that we can check their names against
|
|
|
|
* the actual value of a _recent_contributors variable
|
|
|
|
* @param Title $title
|
|
|
|
* @return string[]
|
|
|
|
*/
|
|
|
|
private function computeRecentContributors( Title $title ) {
|
|
|
|
// This test uses a custom DB query and it's hard to use mocks
|
|
|
|
$user = $this->getMutableTestUser()->getUser();
|
|
|
|
// Create the page and make a couple of edits from different users
|
|
|
|
$this->editPage(
|
2022-06-28 20:46:45 +00:00
|
|
|
$title,
|
2020-01-13 13:07:34 +00:00
|
|
|
'AbuseFilter test for title variables',
|
|
|
|
'',
|
2022-06-28 20:46:45 +00:00
|
|
|
NS_MAIN,
|
2020-01-13 13:07:34 +00:00
|
|
|
$user
|
|
|
|
);
|
|
|
|
$mockContributors = [ 'X>Alice', 'X>Bob', 'X>Charlie' ];
|
|
|
|
foreach ( $mockContributors as $contributor ) {
|
|
|
|
$this->editPage(
|
2022-06-28 20:46:45 +00:00
|
|
|
$title,
|
2020-01-13 13:07:34 +00:00
|
|
|
"page revision by $contributor",
|
|
|
|
'',
|
2022-06-28 20:46:45 +00:00
|
|
|
NS_MAIN,
|
2022-07-02 12:45:19 +00:00
|
|
|
new UltimateAuthority( UserIdentityValue::newAnonymous( $contributor ) )
|
2020-01-13 13:07:34 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
$contributors = array_reverse( $mockContributors );
|
|
|
|
$contributors[] = $user->getName();
|
|
|
|
return $contributors;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2021-01-08 17:17:41 +00:00
|
|
|
* @covers ::compute
|
|
|
|
* @covers ::getLastPageAuthors
|
2020-01-13 13:07:34 +00:00
|
|
|
*/
|
2021-01-14 16:18:13 +00:00
|
|
|
public function testRecentContributors() {
|
|
|
|
$varName = "page_recent_contributors";
|
2022-06-28 20:46:45 +00:00
|
|
|
$title = Title::makeTitle( NS_MAIN, "Page to test $varName" );
|
2020-01-13 13:07:34 +00:00
|
|
|
|
2021-01-08 14:59:56 +00:00
|
|
|
$expected = $this->computeRecentContributors( $title );
|
2021-01-14 16:18:13 +00:00
|
|
|
$computer = AbuseFilterServices::getLazyVariableComputer();
|
|
|
|
$var = new LazyLoadedVariable(
|
|
|
|
'load-recent-authors',
|
|
|
|
[ 'title' => $title ]
|
2021-01-08 14:59:56 +00:00
|
|
|
);
|
2021-04-30 18:54:17 +00:00
|
|
|
$forbidComputeCB = static function () {
|
2021-01-14 16:18:13 +00:00
|
|
|
throw new LogicException( 'Not expected to be called' );
|
|
|
|
};
|
|
|
|
$actual = $computer->compute( $var, new VariableHolder(), $forbidComputeCB )->toNative();
|
|
|
|
$this->assertSame( $expected, $actual );
|
2020-01-13 13:07:34 +00:00
|
|
|
}
|
|
|
|
}
|