Have Parsoid\Config\PageConfigFactory take a rev instead of wikitext
* This let us pass mocked revisions in the parser test runner while running in Parsoid mode. * This leads to improvement in wt2html tests results where a revision id is queried. I've verified this in the Cite extension repo as also the main parserTests.text file but I cannot enable Parsoid integrated testing on the main parser tests file without doing a sweep over all parser tests and adding appropriate test sections * Currently, PageConfigFactory doesn't have unit tests. Will look into adding them separately in a followup. * Moved the setupParsoidTransform function to a more suitable place in the ParserTestRunner.php file. Bug: T270310 Change-Id: I94d68c8528bb2f7b367c68d80d14ebc1ab904a7f
This commit is contained in:
parent
29578f449e
commit
5f5b4cbbb4
4 changed files with 91 additions and 80 deletions
|
|
@ -34,7 +34,6 @@ use MediaWiki\Revision\RevisionRecord;
|
|||
use ParserCache;
|
||||
use ParserOptions;
|
||||
use ParserOutput;
|
||||
use TitleValue;
|
||||
use User;
|
||||
use Wikimedia\Message\MessageValue;
|
||||
use Wikimedia\ParamValidator\ParamValidator;
|
||||
|
|
@ -230,11 +229,7 @@ class ParsoidHTMLHelper {
|
|||
// TODO: make ParsoidPageConfigFactory take PageReference as well
|
||||
return MediaWikiServices::getInstance()
|
||||
->get( 'ParsoidPageConfigFactory' )
|
||||
->create(
|
||||
TitleValue::newFromPage( $this->page ),
|
||||
null,
|
||||
$this->revision ? $this->revision->getId() : null
|
||||
);
|
||||
->create( $this->page, null, $this->revision );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -31,7 +31,9 @@ use MediaWiki\Rest\HttpException;
|
|||
use MediaWiki\Rest\LocalizedHttpException;
|
||||
use MediaWiki\Rest\Response;
|
||||
use MediaWiki\Rest\ResponseException;
|
||||
use MediaWiki\Revision\MutableRevisionRecord;
|
||||
use MediaWiki\Revision\RevisionAccessException;
|
||||
use MediaWiki\Revision\SlotRecord;
|
||||
use MobileContext;
|
||||
use ParserOutput;
|
||||
use RequestContext;
|
||||
|
|
@ -53,6 +55,7 @@ use Wikimedia\Parsoid\Utils\ContentUtils;
|
|||
use Wikimedia\Parsoid\Utils\DOMCompat;
|
||||
use Wikimedia\Parsoid\Utils\DOMUtils;
|
||||
use Wikimedia\Parsoid\Utils\Timing;
|
||||
use WikitextContent;
|
||||
|
||||
/**
|
||||
* Base class for Parsoid handlers.
|
||||
|
|
@ -364,6 +367,24 @@ abstract class ParsoidHandler extends Handler {
|
|||
throw new LogicException( 'Title not found!' );
|
||||
}
|
||||
$user = RequestContext::getMain()->getUser();
|
||||
|
||||
if ( $wikitextOverride === null ) {
|
||||
$revisionRecord = null;
|
||||
} else {
|
||||
// Create a mutable revision record point to the same revision
|
||||
// and set to the desired wikitext.
|
||||
$revisionRecord = new MutableRevisionRecord( $title );
|
||||
if ( $revision !== null ) {
|
||||
$revisionRecord->setId( $revision );
|
||||
}
|
||||
$revisionRecord->setSlot(
|
||||
SlotRecord::newUnsaved(
|
||||
SlotRecord::MAIN,
|
||||
new WikitextContent( $wikitextOverride )
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Note: Parsoid by design isn't supposed to use the user
|
||||
// context right now, and all user state is expected to be
|
||||
// introduced as a post-parse transform. So although we pass a
|
||||
|
|
@ -371,7 +392,7 @@ abstract class ParsoidHandler extends Handler {
|
|||
// corner cases; see PageConfigFactory::create() for more.
|
||||
// @phan-suppress-next-line PhanUndeclaredMethod method defined in subtype
|
||||
return $this->pageConfigFactory->create(
|
||||
$title, $user, $revision, $wikitextOverride, $pagelanguageOverride,
|
||||
$title, $user, $revisionRecord ?? $revision, null, $pagelanguageOverride,
|
||||
$this->parsoidSettings
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,9 +19,8 @@
|
|||
|
||||
namespace MediaWiki\Parser\Parsoid\Config;
|
||||
|
||||
use MediaWiki\Linker\LinkTarget;
|
||||
use MediaWiki\Logger\LoggerFactory;
|
||||
use MediaWiki\Revision\MutableRevisionRecord;
|
||||
use MediaWiki\Page\PageIdentity;
|
||||
use MediaWiki\Revision\RevisionAccessException;
|
||||
use MediaWiki\Revision\RevisionRecord;
|
||||
use MediaWiki\Revision\RevisionStore;
|
||||
|
|
@ -63,41 +62,52 @@ class PageConfigFactory extends \Wikimedia\Parsoid\Config\PageConfigFactory {
|
|||
*
|
||||
* Note that Parsoid isn't supposed to use the user context by design; all
|
||||
* user-specific processing is expected to be introduced as a post-parse
|
||||
* transform. The $user parameter is therefore usually null, especially
|
||||
* transform. The $user parameter is therefore usually null, especially
|
||||
* in background job parsing, although there are corner cases during
|
||||
* extension processing where a non-null $user could affect the output.
|
||||
*
|
||||
* @param LinkTarget $title The page represented by the PageConfig.
|
||||
* @param PageIdentity $pageId The page represented by the PageConfig.
|
||||
* @param ?UserIdentity $user User who is doing rendering (for parsing options).
|
||||
* @param ?int $revisionId The revision of the page.
|
||||
* @param ?string $wikitextOverride Wikitext to use instead of the
|
||||
* contents of the specific $revision; used when $revision is null
|
||||
* (a new page) or when we are parsing a stashed text.
|
||||
* @param int|RevisionRecord|null $revision Revision id or a revision record
|
||||
* @param ?string $unused
|
||||
* @param ?string $pagelanguageOverride
|
||||
* @param ?array $parsoidSettings Used to enable the debug API if requested
|
||||
* @return \Wikimedia\Parsoid\Config\PageConfig
|
||||
*/
|
||||
public function create(
|
||||
LinkTarget $title,
|
||||
PageIdentity $pageId,
|
||||
?UserIdentity $user = null,
|
||||
?int $revisionId = null,
|
||||
?string $wikitextOverride = null,
|
||||
$revision = null,
|
||||
?string $unused = null, /* Added to mollify CI with cross-repo uses */
|
||||
?string $pagelanguageOverride = null,
|
||||
?array $parsoidSettings = null
|
||||
): \Wikimedia\Parsoid\Config\PageConfig {
|
||||
$title = Title::newFromLinkTarget( $title );
|
||||
$title = Title::castFromPageIdentity( $pageId );
|
||||
'@phan-var Title $title';
|
||||
|
||||
if ( !empty( $parsoidSettings['debugApi'] ) ) {
|
||||
return ApiPageConfig::fromSettings( $parsoidSettings, [
|
||||
"title" => $title->getPrefixedText(),
|
||||
"pageContent" => $wikitextOverride,
|
||||
"pageLanguage" => $pagelanguageOverride,
|
||||
"revid" => $revisionId,
|
||||
"loadData" => true,
|
||||
] );
|
||||
if ( $revision === null ) {
|
||||
throw new \InvalidArgumentException(
|
||||
"Revision not provided. Cannot lookup revision via debug API." );
|
||||
}
|
||||
|
||||
$content = $revision->getContent( SlotRecord::MAIN );
|
||||
if ( $content instanceof WikitextContent ) {
|
||||
$wtContent = $content->getText();
|
||||
return ApiPageConfig::fromSettings( $parsoidSettings, [
|
||||
"title" => $title->getPrefixedText(),
|
||||
"pageContent" => $wtContent,
|
||||
"pageLanguage" => $pagelanguageOverride,
|
||||
"revid" => $revision->getId(),
|
||||
"loadData" => true,
|
||||
] );
|
||||
} else {
|
||||
throw new \UnexpectedValueException(
|
||||
"Non-wikitext content models not supported by debug API" );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $revisionId === null ) {
|
||||
if ( $revision === null ) {
|
||||
// Fetch the 'latest' revision for the given title.
|
||||
// Note: This initial fetch of the page context revision is
|
||||
// *not* using Parser::fetchCurrentRevisionRecordOfTitle()
|
||||
|
|
@ -110,31 +120,31 @@ class PageConfigFactory extends \Wikimedia\Parsoid\Config\PageConfigFactory {
|
|||
) ?: null;
|
||||
// Note that $revisionRecord could still be null here if no
|
||||
// page with that $title yet exists.
|
||||
} elseif ( !is_int( $revision ) ) {
|
||||
$revisionRecord = $revision;
|
||||
} else {
|
||||
// Fetch the correct revision record by the supplied id.
|
||||
// This accesses the replica DB and may (or may not) fail over to
|
||||
// the primary DB if the revision isn't found.
|
||||
$revisionRecord = $this->revisionStore->getRevisionById(
|
||||
$revisionId
|
||||
);
|
||||
$revisionRecord = $this->revisionStore->getRevisionById( $revision );
|
||||
if ( $revisionRecord === null ) {
|
||||
// This revision really ought to exist. Check the primary DB.
|
||||
// This *could* cause two requests to the primary DB if there
|
||||
// were pending writes, but this codepath should be very rare.
|
||||
// [T259855]
|
||||
$revisionRecord = $this->revisionStore->getRevisionById(
|
||||
$revisionId, RevisionStore::READ_LATEST
|
||||
$revision, RevisionStore::READ_LATEST
|
||||
);
|
||||
$success = ( $revisionRecord !== null ) ? 'success' : 'failure';
|
||||
LoggerFactory::getInstance( 'Parsoid' )->error(
|
||||
"Retried revision fetch after failure: {$success}", [
|
||||
'id' => $revisionId,
|
||||
'id' => $revision,
|
||||
'title' => $title->getPrefixedText(),
|
||||
]
|
||||
);
|
||||
}
|
||||
if ( $revisionRecord === null ) {
|
||||
throw new RevisionAccessException( "Can't find revision {$revisionId}" );
|
||||
throw new RevisionAccessException( "Can't find revision {$revision}" );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -149,24 +159,6 @@ class PageConfigFactory extends \Wikimedia\Parsoid\Config\PageConfigFactory {
|
|||
throw new RevisionAccessException( 'Not an available content version.' );
|
||||
}
|
||||
|
||||
if ( $wikitextOverride !== null ) {
|
||||
if ( $revisionRecord ) {
|
||||
// PORT-FIXME this is not really the right thing to do; need
|
||||
// a clone-like constructor for MutableRevisionRecord
|
||||
$revisionRecord = MutableRevisionRecord::newFromParentRevision(
|
||||
$revisionRecord
|
||||
);
|
||||
} else {
|
||||
$revisionRecord = new MutableRevisionRecord( $title );
|
||||
}
|
||||
$revisionRecord->setSlot(
|
||||
SlotRecord::newUnsaved(
|
||||
SlotRecord::MAIN,
|
||||
new WikitextContent( $wikitextOverride )
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$parserOptions =
|
||||
$user
|
||||
? ParserOptions::newFromUser( $user )
|
||||
|
|
|
|||
|
|
@ -1572,35 +1572,6 @@ class ParserTestRunner {
|
|||
);
|
||||
}
|
||||
|
||||
private function setupParsoidTransform( ParserTest $test ): array {
|
||||
$services = MediaWikiServices::getInstance();
|
||||
$pageConfigFactory = $services->get( 'ParsoidPageConfigFactory' );
|
||||
$pageConfig = null;
|
||||
[ $title, $options, $revId ] = $this->setupParserOptions(
|
||||
$test,
|
||||
static function ( $context, $title, $revId, $wikitext ) use ( $pageConfigFactory, &$pageConfig ) {
|
||||
$pageConfig = $pageConfigFactory->create(
|
||||
$title,
|
||||
$context->getUser(),
|
||||
// @todo T270310: Parsoid doesn't have a mechanism
|
||||
// to override revid with a fake revision, like the
|
||||
// legacy parser does, so {{REVISIONID}} will be
|
||||
// 'wrong' in parser tests. Probably need to
|
||||
// override
|
||||
// ParserOptions::getCurrentRevisionRecordCallback()
|
||||
// (like we do for the 'lastsavedrevision' option
|
||||
// below) in order to fix this.
|
||||
null/*$revId*/,
|
||||
// @todo T270310: Parsoid should really accept a
|
||||
// RevisionRecord here, instead of raw wikitext.
|
||||
$wikitext,
|
||||
$context->getLanguage()->getCode()
|
||||
);
|
||||
return $pageConfig->getParserOptions();
|
||||
} );
|
||||
return [ $pageConfig, $title, $options, $revId ];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Parsoid $parsoid
|
||||
* @param PageConfig $pageConfig
|
||||
|
|
@ -1771,6 +1742,38 @@ class ParserTestRunner {
|
|||
}
|
||||
}
|
||||
|
||||
private function setupParsoidTransform( ParserTest $test ): array {
|
||||
$services = MediaWikiServices::getInstance();
|
||||
$pageConfigFactory = $services->get( 'ParsoidPageConfigFactory' );
|
||||
$pageConfig = null;
|
||||
$runner = $this;
|
||||
[ $title, $options, $revId ] = $this->setupParserOptions(
|
||||
$test,
|
||||
static function ( $context, $title, $revId, $wikitext ) use ( $runner, $pageConfigFactory, &$pageConfig ) {
|
||||
$user = $context->getUser();
|
||||
$content = new WikitextContent( $wikitext );
|
||||
$title = Title::newFromRow( (object)[
|
||||
'page_id' => 187,
|
||||
'page_len' => $content->getSize(),
|
||||
'page_latest' => 1337,
|
||||
'page_namespace' => $title->getNamespace(),
|
||||
'page_title' => $title->getDBkey(),
|
||||
'page_is_redirect' => 0
|
||||
] );
|
||||
$revRecord = new MutableRevisionRecord( $title );
|
||||
$revRecord->setContent( SlotRecord::MAIN, $content )
|
||||
->setUser( $user )
|
||||
->setTimestamp( strval( $runner->getFakeTimestamp() ) )
|
||||
->setPageId( $title->getArticleID() )
|
||||
->setId( $title->getLatestRevID() );
|
||||
$pageConfig = $pageConfigFactory->create(
|
||||
$title, $user, $revRecord, $context->getLanguage()->getCode()
|
||||
);
|
||||
return $pageConfig->getParserOptions();
|
||||
} );
|
||||
return [ $pageConfig, $title, $options, $revId ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to register a Parsoid extension module in such a
|
||||
* way that it can be cleaned up after the test is complete.
|
||||
|
|
|
|||
Loading…
Reference in a new issue