+<?php
+use MediaWiki\MediaWikiServices;
+use MediaWiki\Storage\MutableRevisionRecord;
+use MediaWiki\Storage\RevisionRecord;
+
+/**
+ * @covers PoolWorkArticleView
+ */
+class PoolWorkArticleViewTest extends MediaWikiTestCase {
+
+ private function makeRevision( WikiPage $page, $text ) {
+ $user = $this->getTestUser()->getUser();
+ $updater = $page->newPageUpdater( $user );
+
+ $updater->setContent( 'main', new WikitextContent( $text ) );
+ return $updater->saveRevision( CommentStoreComment::newUnsavedComment( 'testing' ) );
+ }
+
+ public function testDoWorkLoadRevision() {
+ $options = ParserOptions::newCanonical( 'canonical' );
+ $page = $this->getExistingTestPage( __METHOD__ );
+ $rev1 = $this->makeRevision( $page, 'First!' );
+ $rev2 = $this->makeRevision( $page, 'Second!' );
+
+ $work = new PoolWorkArticleView( $page, $options, $rev1->getId(), false );
+ $work->execute();
+ $this->assertContains( 'First', $work->getParserOutput()->getText() );
+
+ $work = new PoolWorkArticleView( $page, $options, $rev2->getId(), false );
+ $work->execute();
+ $this->assertContains( 'Second', $work->getParserOutput()->getText() );
+ }
+
+ public function testDoWorkParserCache() {
+ $options = ParserOptions::newCanonical( 'canonical' );
+ $page = $this->getExistingTestPage( __METHOD__ );
+ $rev1 = $this->makeRevision( $page, 'First!' );
+
+ $work = new PoolWorkArticleView( $page, $options, $rev1->getId(), true );
+ $work->execute();
+
+ $cache = MediaWikiServices::getInstance()->getParserCache();
+ $out = $cache->get( $page, $options );
+
+ $this->assertNotNull( $out );
+ $this->assertNotFalse( $out );
+ $this->assertContains( 'First', $out->getText() );
+ }
+
+ public function testDoWorkWithExplicitRevision() {
+ $options = ParserOptions::newCanonical( 'canonical' );
+ $page = $this->getExistingTestPage( __METHOD__ );
+ $rev = $this->makeRevision( $page, 'NOPE' );
+
+ // make a fake revision with different content, so we know it's actually being used!
+ $fakeRev = new MutableRevisionRecord( $page->getTitle() );
+ $fakeRev->setId( $rev->getId() );
+ $fakeRev->setPageId( $page->getId() );
+ $fakeRev->setContent( 'main', new WikitextContent( 'YES!' ) );
+
+ $work = new PoolWorkArticleView( $page, $options, $rev->getId(), false, $fakeRev );
+ $work->execute();
+
+ $text = $work->getParserOutput()->getText();
+ $this->assertContains( 'YES!', $text );
+ $this->assertNotContains( 'NOPE', $text );
+ }
+
+ public function testDoWorkWithContent() {
+ $options = ParserOptions::newCanonical( 'canonical' );
+ $page = $this->getExistingTestPage( __METHOD__ );
+
+ $content = new WikitextContent( 'YES!' );
+
+ $work = new PoolWorkArticleView( $page, $options, $page->getLatest(), false, $content );
+ $work->execute();
+
+ $text = $work->getParserOutput()->getText();
+ $this->assertContains( 'YES!', $text );
+ }
+
+ public function testDoWorkWithString() {
+ $options = ParserOptions::newCanonical( 'canonical' );
+ $page = $this->getExistingTestPage( __METHOD__ );
+
+ $work = new PoolWorkArticleView( $page, $options, $page->getLatest(), false, 'YES!' );
+ $work->execute();
+
+ $text = $work->getParserOutput()->getText();
+ $this->assertContains( 'YES!', $text );
+ }
+
+ public function provideMagicWords() {
+ yield 'PAGEID' => [
+ 'Test {{PAGEID}} Test',
+ function ( RevisionRecord $rev ) {
+ return $rev->getPageId();
+ }
+ ];
+ yield 'REVISIONID' => [
+ 'Test {{REVISIONID}} Test',
+ function ( RevisionRecord $rev ) {
+ return $rev->getId();
+ }
+ ];
+ yield 'REVISIONUSER' => [
+ 'Test {{REVISIONUSER}} Test',
+ function ( RevisionRecord $rev ) {
+ return $rev->getUser()->getName();
+ }
+ ];
+ yield 'REVISIONTIMESTAMP' => [
+ 'Test {{REVISIONTIMESTAMP}} Test',
+ function ( RevisionRecord $rev ) {
+ return $rev->getTimestamp();
+ }
+ ];
+ }
+ /**
+ * @dataProvider provideMagicWords
+ */
+ public function testMagicWords( $wikitext, $callback ) {
+ $options = ParserOptions::newCanonical( 'canonical' );
+ $page = $this->getExistingTestPage( __METHOD__ );
+ $rev = $page->getRevision()->getRevisionRecord();
+
+ // 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.
+ $work = new PoolWorkArticleView( $page, $options, $page->getLatest(), false, $wikitext );
+ $work->execute();
+
+ $expected = strval( $callback( $rev ) );
+ $output = $work->getParserOutput();
+
+ $this->assertContains( $expected, $output->getText() );
+ }
+
+ public function testDoWorkMissingPage() {
+ $options = ParserOptions::newCanonical( 'canonical' );
+ $page = $this->getNonexistingTestPage();
+
+ $work = new PoolWorkArticleView( $page, $options, '667788', false );
+ $this->assertFalse( $work->execute() );
+ }
+
+ public function testDoWorkDeletedContent() {
+ $options = ParserOptions::newCanonical( 'canonical' );
+ $page = $this->getExistingTestPage( __METHOD__ );
+ $rev1 = $page->getRevision()->getRevisionRecord();
+
+ // 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() );
+ $fakeRev->setContent( 'main', new WikitextContent( 'SECRET' ) );
+ $fakeRev->setVisibility( RevisionRecord::DELETED_TEXT );
+
+ $work = new PoolWorkArticleView( $page, $options, $rev1->getId(), false, $fakeRev );
+ $this->assertFalse( $work->execute() );
+
+ // a deleted current revision should still be show
+ $fakeRev->setId( $rev2->getId() );
+ $work = new PoolWorkArticleView( $page, $options, $rev2->getId(), false, $fakeRev );
+ $this->assertNotFalse( $work->execute() );
+ }
+
+}