2018-08-14 16:37:30 +00:00
|
|
|
<?php
|
2019-05-28 14:04:23 +00:00
|
|
|
|
2023-12-11 14:59:55 +00:00
|
|
|
use MediaWiki\CommentStore\CommentStoreComment;
|
2020-11-17 20:34:43 +00:00
|
|
|
use MediaWiki\Logger\Spi as LoggerSpi;
|
2023-12-15 15:52:25 +00:00
|
|
|
use MediaWiki\PoolCounter\PoolWorkArticleView;
|
2018-09-20 17:29:04 +00:00
|
|
|
use MediaWiki\Revision\MutableRevisionRecord;
|
|
|
|
|
use MediaWiki\Revision\RevisionRecord;
|
|
|
|
|
use MediaWiki\Revision\SlotRecord;
|
2023-08-25 12:29:41 +00:00
|
|
|
use MediaWiki\Status\Status;
|
2020-11-17 20:34:43 +00:00
|
|
|
use Psr\Log\LoggerInterface;
|
|
|
|
|
use Psr\Log\NullLogger;
|
2018-08-14 16:37:30 +00:00
|
|
|
|
|
|
|
|
/**
|
2024-01-27 00:11:07 +00:00
|
|
|
* @covers \MediaWiki\PoolCounter\PoolWorkArticleView
|
2018-09-14 18:30:30 +00:00
|
|
|
* @group Database
|
2018-08-14 16:37:30 +00:00
|
|
|
*/
|
2020-06-30 15:09:24 +00:00
|
|
|
class PoolWorkArticleViewTest extends MediaWikiIntegrationTestCase {
|
2018-08-14 16:37:30 +00:00
|
|
|
|
2020-11-17 20:34:43 +00:00
|
|
|
/**
|
|
|
|
|
* @param LoggerInterface|null $logger
|
|
|
|
|
*
|
|
|
|
|
* @return LoggerSpi
|
|
|
|
|
*/
|
|
|
|
|
protected function getLoggerSpi( $logger = null ) {
|
|
|
|
|
$logger = $logger ?: new NullLogger();
|
|
|
|
|
$spi = $this->createNoOpMock( LoggerSpi::class, [ 'getLogger' ] );
|
|
|
|
|
$spi->method( 'getLogger' )->willReturn( $logger );
|
|
|
|
|
return $spi;
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-13 11:46:05 +00:00
|
|
|
/**
|
|
|
|
|
* @param WikiPage $page
|
2020-11-16 20:05:03 +00:00
|
|
|
* @param RevisionRecord|null $rev
|
|
|
|
|
* @param ParserOptions|null $options
|
2020-11-13 11:46:05 +00:00
|
|
|
*
|
|
|
|
|
* @return PoolWorkArticleView
|
|
|
|
|
*/
|
2020-11-16 20:05:03 +00:00
|
|
|
protected function newPoolWorkArticleView(
|
2020-11-13 11:46:05 +00:00
|
|
|
WikiPage $page,
|
|
|
|
|
RevisionRecord $rev = null,
|
2020-11-16 20:05:03 +00:00
|
|
|
$options = null
|
2020-11-13 11:46:05 +00:00
|
|
|
) {
|
|
|
|
|
if ( !$options ) {
|
2022-06-16 13:22:24 +00:00
|
|
|
$options = ParserOptions::newFromAnon();
|
2020-11-13 11:46:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( !$rev ) {
|
|
|
|
|
$rev = $page->getRevisionRecord();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$revisionRenderer = $this->getServiceContainer()->getRevisionRenderer();
|
|
|
|
|
|
|
|
|
|
return new PoolWorkArticleView(
|
2020-11-16 20:05:03 +00:00
|
|
|
'test:' . $rev->getId(),
|
2020-11-13 11:46:05 +00:00
|
|
|
$rev,
|
|
|
|
|
$options,
|
2020-11-17 20:34:43 +00:00
|
|
|
$revisionRenderer,
|
|
|
|
|
$this->getLoggerSpi()
|
2020-11-13 11:46:05 +00:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-14 16:37:30 +00:00
|
|
|
private function makeRevision( WikiPage $page, $text ) {
|
|
|
|
|
$user = $this->getTestUser()->getUser();
|
2021-10-04 17:10:37 +00:00
|
|
|
$revision = $page->newPageUpdater( $user )
|
2021-09-22 23:03:30 +00:00
|
|
|
->setContent( SlotRecord::MAIN, new WikitextContent( $text ) )
|
|
|
|
|
->saveRevision( CommentStoreComment::newUnsavedComment( 'testing' ) );
|
2018-08-14 16:37:30 +00:00
|
|
|
|
2021-10-04 17:10:37 +00:00
|
|
|
return $revision;
|
2018-08-14 16:37:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testDoWorkLoadRevision() {
|
2022-06-16 13:22:24 +00:00
|
|
|
$options = ParserOptions::newFromAnon();
|
2018-08-14 16:37:30 +00:00
|
|
|
$page = $this->getExistingTestPage( __METHOD__ );
|
|
|
|
|
$rev1 = $this->makeRevision( $page, 'First!' );
|
|
|
|
|
$rev2 = $this->makeRevision( $page, 'Second!' );
|
|
|
|
|
|
2020-11-16 20:05:03 +00:00
|
|
|
$work = $this->newPoolWorkArticleView( $page, $rev1, $options );
|
2022-04-05 16:37:01 +00:00
|
|
|
/** @var Status $status */
|
|
|
|
|
$status = $work->execute();
|
|
|
|
|
$this->assertStringContainsString( 'First', $status->getValue()->getText() );
|
2018-08-14 16:37:30 +00:00
|
|
|
|
2020-11-16 20:05:03 +00:00
|
|
|
$work = $this->newPoolWorkArticleView( $page, $rev2, $options );
|
2022-04-05 16:37:01 +00:00
|
|
|
/** @var Status $status */
|
|
|
|
|
$status = $work->execute();
|
|
|
|
|
$this->assertStringContainsString( 'Second', $status->getValue()->getText() );
|
2018-08-14 16:37:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testDoWorkParserCache() {
|
2022-06-16 13:22:24 +00:00
|
|
|
$options = ParserOptions::newFromAnon();
|
2018-08-14 16:37:30 +00:00
|
|
|
$page = $this->getExistingTestPage( __METHOD__ );
|
|
|
|
|
$rev1 = $this->makeRevision( $page, 'First!' );
|
|
|
|
|
|
2020-11-16 20:05:03 +00:00
|
|
|
$work = $this->newPoolWorkArticleView( $page, $rev1, $options );
|
2018-08-14 16:37:30 +00:00
|
|
|
$work->execute();
|
|
|
|
|
|
2022-01-12 20:13:39 +00:00
|
|
|
$cache = $this->getServiceContainer()->getParserCache();
|
2018-08-14 16:37:30 +00:00
|
|
|
$out = $cache->get( $page, $options );
|
|
|
|
|
|
|
|
|
|
$this->assertNotNull( $out );
|
|
|
|
|
$this->assertNotFalse( $out );
|
2019-12-14 10:27:56 +00:00
|
|
|
$this->assertStringContainsString( 'First', $out->getText() );
|
2018-08-14 16:37:30 +00:00
|
|
|
}
|
|
|
|
|
|
2020-11-13 11:46:05 +00:00
|
|
|
public function testDoWorkWithFakeRevision() {
|
2022-06-16 13:22:24 +00:00
|
|
|
$options = ParserOptions::newFromAnon();
|
2018-08-14 16:37:30 +00:00
|
|
|
$page = $this->getExistingTestPage( __METHOD__ );
|
|
|
|
|
$rev = $this->makeRevision( $page, 'NOPE' );
|
|
|
|
|
|
2020-11-13 11:46:05 +00:00
|
|
|
// Make a fake revision with different content and no revision ID or page ID,
|
|
|
|
|
// and make sure the fake content is used.
|
2018-08-14 16:37:30 +00:00
|
|
|
$fakeRev = new MutableRevisionRecord( $page->getTitle() );
|
2018-09-24 21:10:08 +00:00
|
|
|
$fakeRev->setContent( SlotRecord::MAIN, new WikitextContent( 'YES!' ) );
|
2018-08-14 16:37:30 +00:00
|
|
|
|
2020-11-16 20:05:03 +00:00
|
|
|
$work = $this->newPoolWorkArticleView( $page, $fakeRev, $options );
|
2022-04-05 16:37:01 +00:00
|
|
|
/** @var Status $status */
|
|
|
|
|
$status = $work->execute();
|
2018-08-14 16:37:30 +00:00
|
|
|
|
2022-04-05 16:37:01 +00:00
|
|
|
$text = $status->getValue()->getText();
|
2019-12-14 10:27:56 +00:00
|
|
|
$this->assertStringContainsString( 'YES!', $text );
|
|
|
|
|
$this->assertStringNotContainsString( 'NOPE', $text );
|
2018-08-14 16:37:30 +00:00
|
|
|
}
|
|
|
|
|
|
2023-03-23 11:36:19 +00:00
|
|
|
public static function provideMagicWords() {
|
2018-08-14 16:37:30 +00:00
|
|
|
yield 'PAGEID' => [
|
|
|
|
|
'Test {{PAGEID}} Test',
|
2021-02-07 13:10:36 +00:00
|
|
|
static function ( RevisionRecord $rev ) {
|
2018-08-14 16:37:30 +00:00
|
|
|
return $rev->getPageId();
|
|
|
|
|
}
|
|
|
|
|
];
|
|
|
|
|
yield 'REVISIONID' => [
|
|
|
|
|
'Test {{REVISIONID}} Test',
|
2021-02-07 13:10:36 +00:00
|
|
|
static function ( RevisionRecord $rev ) {
|
2018-08-14 16:37:30 +00:00
|
|
|
return $rev->getId();
|
|
|
|
|
}
|
|
|
|
|
];
|
|
|
|
|
yield 'REVISIONUSER' => [
|
|
|
|
|
'Test {{REVISIONUSER}} Test',
|
2021-02-07 13:10:36 +00:00
|
|
|
static function ( RevisionRecord $rev ) {
|
2018-08-14 16:37:30 +00:00
|
|
|
return $rev->getUser()->getName();
|
|
|
|
|
}
|
|
|
|
|
];
|
|
|
|
|
yield 'REVISIONTIMESTAMP' => [
|
|
|
|
|
'Test {{REVISIONTIMESTAMP}} Test',
|
2021-02-07 13:10:36 +00:00
|
|
|
static function ( RevisionRecord $rev ) {
|
2018-08-14 16:37:30 +00:00
|
|
|
return $rev->getTimestamp();
|
|
|
|
|
}
|
|
|
|
|
];
|
|
|
|
|
}
|
2019-01-15 15:04:58 +00:00
|
|
|
|
2018-08-14 16:37:30 +00:00
|
|
|
/**
|
|
|
|
|
* @dataProvider provideMagicWords
|
|
|
|
|
*/
|
|
|
|
|
public function testMagicWords( $wikitext, $callback ) {
|
2020-11-13 11:46:05 +00:00
|
|
|
static $counter = 1;
|
|
|
|
|
|
2022-06-16 13:22:24 +00:00
|
|
|
$options = ParserOptions::newFromAnon();
|
2020-11-13 11:46:05 +00:00
|
|
|
$page = $this->getNonexistingTestPage( __METHOD__ . $counter++ );
|
|
|
|
|
$this->editPage( $page, $wikitext );
|
2020-04-18 02:39:58 +00:00
|
|
|
$rev = $page->getRevisionRecord();
|
2018-08-14 16:37:30 +00:00
|
|
|
|
|
|
|
|
// NOTE: provide the input as a string and let the PoolWorkArticleView create a fake
|
|
|
|
|
// revision internally, to see if the magic words work with that fake. They should
|
|
|
|
|
// work if the Parser causes the actual revision to be loaded when needed.
|
2020-11-13 11:46:05 +00:00
|
|
|
$work = $this->newPoolWorkArticleView(
|
|
|
|
|
$page,
|
|
|
|
|
$page->getRevisionRecord(),
|
|
|
|
|
$options,
|
|
|
|
|
false
|
|
|
|
|
);
|
2022-04-05 16:37:01 +00:00
|
|
|
/** @var Status $status */
|
|
|
|
|
$status = $work->execute();
|
2018-08-14 16:37:30 +00:00
|
|
|
|
|
|
|
|
$expected = strval( $callback( $rev ) );
|
2022-04-05 16:37:01 +00:00
|
|
|
$output = $status->getValue();
|
2018-08-14 16:37:30 +00:00
|
|
|
|
2019-12-14 12:45:35 +00:00
|
|
|
$this->assertStringContainsString( $expected, $output->getText() );
|
2018-08-14 16:37:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testDoWorkDeletedContent() {
|
2022-06-16 13:22:24 +00:00
|
|
|
$options = ParserOptions::newFromAnon();
|
2018-08-14 16:37:30 +00:00
|
|
|
$page = $this->getExistingTestPage( __METHOD__ );
|
2020-04-18 02:39:58 +00:00
|
|
|
$rev1 = $page->getRevisionRecord();
|
2018-08-14 16:37:30 +00:00
|
|
|
|
|
|
|
|
// make another revision, since the latest revision cannot be deleted.
|
|
|
|
|
$rev2 = $this->makeRevision( $page, 'Next' );
|
|
|
|
|
|
|
|
|
|
// make a fake revision with deleted different content
|
|
|
|
|
$fakeRev = new MutableRevisionRecord( $page->getTitle() );
|
|
|
|
|
$fakeRev->setId( $rev1->getId() );
|
|
|
|
|
$fakeRev->setPageId( $page->getId() );
|
2018-09-24 21:10:08 +00:00
|
|
|
$fakeRev->setContent( SlotRecord::MAIN, new WikitextContent( 'SECRET' ) );
|
2018-08-14 16:37:30 +00:00
|
|
|
$fakeRev->setVisibility( RevisionRecord::DELETED_TEXT );
|
|
|
|
|
|
2020-11-13 11:46:05 +00:00
|
|
|
// rendering of a deleted revision should work, audience checks are bypassed
|
2020-11-16 20:05:03 +00:00
|
|
|
$work = $this->newPoolWorkArticleView( $page, $fakeRev, $options );
|
2022-04-05 16:37:01 +00:00
|
|
|
/** @var Status $status */
|
|
|
|
|
$status = $work->execute();
|
2023-10-04 09:31:23 +00:00
|
|
|
$this->assertStatusGood( $status );
|
2018-08-14 16:37:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|