HtmlOutputRendererHelper: add more convenient setters

REST helper objects should be geared towards accepting input directly
from an HTTP request. As such, they should offer setters that take
string values. And native representation of things like page titles,
languages, or content objects should be done implicitly by the helper.

Change-Id: I9b81cad4d5cc575e7c5283035e385ac0457e8059
This commit is contained in:
daniel 2022-11-24 22:54:11 +01:00
parent c6a0d433ec
commit 93015579a1
6 changed files with 106 additions and 18 deletions

View file

@ -24,8 +24,10 @@ use IBufferingStatsdDataFactory;
use Language;
use Liuggio\StatsdClient\Factory\StatsdDataFactoryInterface;
use LogicException;
use MediaWiki\Content\IContentHandlerFactory;
use MediaWiki\Edit\ParsoidOutputStash;
use MediaWiki\Edit\SelserContext;
use MediaWiki\Languages\LanguageFactory;
use MediaWiki\MainConfigNames;
use MediaWiki\Page\PageIdentity;
use MediaWiki\Page\PageRecord;
@ -34,11 +36,13 @@ use MediaWiki\Parser\Parsoid\PageBundleParserOutputConverter;
use MediaWiki\Parser\Parsoid\ParsoidOutputAccess;
use MediaWiki\Parser\Parsoid\ParsoidRenderID;
use MediaWiki\Rest\Handler;
use MediaWiki\Rest\HttpException;
use MediaWiki\Rest\LocalizedHttpException;
use MediaWiki\Rest\ResponseInterface;
use MediaWiki\Revision\MutableRevisionRecord;
use MediaWiki\Revision\RevisionRecord;
use MediaWiki\Revision\SlotRecord;
use MWUnknownContentModelException;
use ParserOptions;
use ParserOutput;
use User;
@ -101,11 +105,17 @@ class HtmlOutputRendererHelper {
/** @var HtmlTransformFactory */
private $htmlTransformFactory;
/** @var string|null */
private $sourceLanguageCode;
/** @var IContentHandlerFactory */
private $contentHandlerFactory;
/** @var LanguageFactory */
private $languageFactory;
/** @var string|null */
private $targetLanguageCode;
private $sourceLanguageCode = null;
/** @var string|null */
private $targetLanguageCode = null;
/**
* Flags to be passed as $options to ParsoidOutputAccess::getParserOutput,
@ -120,17 +130,23 @@ class HtmlOutputRendererHelper {
* @param StatsdDataFactoryInterface $statsDataFactory
* @param ParsoidOutputAccess $parsoidOutputAccess
* @param HtmlTransformFactory $htmlTransformFactory
* @param IContentHandlerFactory $contentHandlerFactory
* @param LanguageFactory $languageFactory
*/
public function __construct(
ParsoidOutputStash $parsoidOutputStash,
StatsdDataFactoryInterface $statsDataFactory,
ParsoidOutputAccess $parsoidOutputAccess,
HtmlTransformFactory $htmlTransformFactory
HtmlTransformFactory $htmlTransformFactory,
IContentHandlerFactory $contentHandlerFactory,
LanguageFactory $languageFactory
) {
$this->parsoidOutputStash = $parsoidOutputStash;
$this->stats = $statsDataFactory;
$this->parsoidOutputAccess = $parsoidOutputAccess;
$this->htmlTransformFactory = $htmlTransformFactory;
$this->contentHandlerFactory = $contentHandlerFactory;
$this->languageFactory = $languageFactory;
}
/**
@ -201,6 +217,7 @@ class HtmlOutputRendererHelper {
* This will create a fake revision for rendering, the revision ID will be 0.
*
* @see setRevision
* @see setContentSource
*
* @param Content $content
*/
@ -213,9 +230,35 @@ class HtmlOutputRendererHelper {
}
/**
* @param Language $pageLanguage
* Set the content to render. Useful when rendering for previews
* or when switching the editor from source mode to visual mode.
*
* This will create a fake revision for rendering, the revision ID will be 0.
*
* @param string $source The source data, e.g. wikitext
* @param string $model The content model indicating how to interpret $source, e.g. CONTENT_MODEL_WIKITEXT
*
* @see setRevision
* @see setContent
*/
public function setPageLanguage( Language $pageLanguage ): void {
public function setContentSource( string $source, string $model ): void {
try {
$handler = $this->contentHandlerFactory->getContentHandler( $model );
$content = $handler->unserializeContent( $source );
$this->setContent( $content );
} catch ( MWUnknownContentModelException $ex ) {
throw new HttpException( 'Bad content model: ' . $model, 400 );
}
}
/**
* @param Language|string $pageLanguage
*/
public function setPageLanguage( $pageLanguage ): void {
if ( is_string( $pageLanguage ) ) {
$pageLanguage = $this->languageFactory->getLanguage( $pageLanguage );
}
$this->pageLanguage = $pageLanguage;
}
@ -224,7 +267,7 @@ class HtmlOutputRendererHelper {
* @param array $parameters
* @param User $user
* @param RevisionRecord|int|null $revision DEPRECATED, use setRevision()
* @param Language|null $pageLanguage
* @param Language|null $pageLanguage DEPRECATED, use setPageLanguage()
*/
public function init(
PageIdentity $page,
@ -277,7 +320,7 @@ class HtmlOutputRendererHelper {
);
}
$fakeRevision = ( is_object( $this->revisionOrId ) && $this->revisionOrId->getId() < 1 );
$fakeRevision = !$this->getRevisionId() && $this->revisionOrId !== null;
$parsoidStashKey = ParsoidRenderID::newFromKey(
$this->parsoidOutputAccess->getParsoidRenderID( $parserOutput )
);
@ -399,7 +442,7 @@ class HtmlOutputRendererHelper {
// the current revision or the revision must have an ID.
// If we have a revision and the ID is 0 or null, then it's a fake revision
// representing a preview.
$fakeRevision = ( is_object( $this->revisionOrId ) && $this->revisionOrId->getId() < 1 );
$fakeRevision = !$this->getRevisionId() && $this->revisionOrId !== null;
$pageRecordAvailable = $this->page instanceof PageRecord;
if ( $pageRecordAvailable && !$fakeRevision && !$envOptions ) {
@ -483,4 +526,15 @@ class HtmlOutputRendererHelper {
}
}
/**
* Returns the ID of the revision that is being rendered.
* If this is not 0, the rendering is for a revision present in the database.
* If it is 0, the revision is a fake revision representing e.g. a preview.
*
* @return int
*/
public function getRevisionId(): int {
return is_object( $this->revisionOrId ) ? (int)$this->revisionOrId->getId() : (int)$this->revisionOrId;
}
}

View file

@ -4,7 +4,9 @@ namespace MediaWiki\Rest\Handler;
use Liuggio\StatsdClient\Factory\StatsdDataFactoryInterface;
use MediaWiki\Config\ServiceOptions;
use MediaWiki\Content\IContentHandlerFactory;
use MediaWiki\Edit\ParsoidOutputStash;
use MediaWiki\Languages\LanguageFactory;
use MediaWiki\Page\PageLookup;
use MediaWiki\Parser\Parsoid\HtmlTransformFactory;
use MediaWiki\Parser\Parsoid\ParsoidOutputAccess;
@ -29,6 +31,8 @@ class PageRestHelperFactory {
private StatsdDataFactoryInterface $stats;
private ParsoidOutputAccess $parsoidOutputAccess;
private HtmlTransformFactory $htmlTransformFactory;
private IContentHandlerFactory $contentHandlerFactory;
private LanguageFactory $languageFactory;
/**
* @param ServiceOptions $options
@ -39,6 +43,8 @@ class PageRestHelperFactory {
* @param StatsdDataFactoryInterface $statsDataFactory
* @param ParsoidOutputAccess $parsoidOutputAccess
* @param HtmlTransformFactory $htmlTransformFactory
* @param IContentHandlerFactory $contentHandlerFactory
* @param LanguageFactory $languageFactory
*/
public function __construct(
ServiceOptions $options,
@ -48,7 +54,9 @@ class PageRestHelperFactory {
ParsoidOutputStash $parsoidOutputStash,
StatsdDataFactoryInterface $statsDataFactory,
ParsoidOutputAccess $parsoidOutputAccess,
HtmlTransformFactory $htmlTransformFactory
HtmlTransformFactory $htmlTransformFactory,
IContentHandlerFactory $contentHandlerFactory,
LanguageFactory $languageFactory
) {
$this->options = $options;
$this->revisionLookup = $revisionLookup;
@ -58,6 +66,8 @@ class PageRestHelperFactory {
$this->stats = $statsDataFactory;
$this->parsoidOutputAccess = $parsoidOutputAccess;
$this->htmlTransformFactory = $htmlTransformFactory;
$this->contentHandlerFactory = $contentHandlerFactory;
$this->languageFactory = $languageFactory;
}
public function newRevisionContentHelper(): RevisionContentHelper {
@ -83,7 +93,9 @@ class PageRestHelperFactory {
$this->parsoidOutputStash,
$this->stats,
$this->parsoidOutputAccess,
$this->htmlTransformFactory
$this->htmlTransformFactory,
$this->contentHandlerFactory,
$this->languageFactory
);
}

View file

@ -1215,7 +1215,9 @@ return [
$services->getParsoidOutputStash(),
$services->getStatsdDataFactory(),
$services->getParsoidOutputAccess(),
$services->getHtmlTransformFactory()
$services->getHtmlTransformFactory(),
$services->getContentHandlerFactory(),
$services->getLanguageFactory()
);
},

View file

@ -229,11 +229,15 @@ class HtmlOutputRendererHelperTest extends MediaWikiIntegrationTestCase {
$cache = $cache ?: new EmptyBagOStuff();
$stash = new SimpleParsoidOutputStash( $chFactory, $cache, 1 );
$services = $this->getServiceContainer();
$helper = new HtmlOutputRendererHelper(
$stash,
new NullStatsdDataFactory(),
$access ?? $this->newMockParsoidOutputAccess(),
$this->getServiceContainer()->getHtmlTransformFactory()
$services->getHtmlTransformFactory(),
$services->getContentHandlerFactory(),
$services->getLanguageFactory()
);
return $helper;
@ -287,6 +291,7 @@ class HtmlOutputRendererHelperTest extends MediaWikiIntegrationTestCase {
if ( $rev ) {
$helper->setRevision( $rev );
$this->assertSame( $rev, $helper->getRevisionId() );
}
$htmlresult = $helper->getHtml()->getRawText();
@ -306,7 +311,7 @@ class HtmlOutputRendererHelperTest extends MediaWikiIntegrationTestCase {
$this->assertStringContainsString( 'en-x-piglatin', $helper->getETag() );
}
public function testGetPreviewHtml() {
public function testGetPreviewHtml_setContent() {
$page = $this->getNonexistingTestPage();
$helper = $this->newHelper();
@ -318,6 +323,18 @@ class HtmlOutputRendererHelperTest extends MediaWikiIntegrationTestCase {
$this->assertStringContainsString( 'text to preview', $htmlresult );
}
public function testGetPreviewHtml_setContentSource() {
$page = $this->getNonexistingTestPage();
$helper = $this->newHelper();
$helper->init( $page, self::PARAM_DEFAULTS, $this->newUser() );
$helper->setContentSource( 'text to preview', CONTENT_MODEL_WIKITEXT );
$htmlresult = $helper->getHtml()->getRawText();
$this->assertStringContainsString( 'text to preview', $htmlresult );
}
public function testHtmlIsStashedForExistingPage() {
[ $page, ] = $this->getExistingPageWithRevisions( __METHOD__ );
@ -684,13 +701,12 @@ class HtmlOutputRendererHelperTest extends MediaWikiIntegrationTestCase {
}
public function testGetParserOutputWithLanguageOverride() {
$language = $this->getLanguageMock( 'ar' );
$helper = $this->newHelper();
[ $page, $revision ] = $this->getNonExistingPageWithFakeRevision( __METHOD__ );
$helper->init( $page, [], $this->newUser(), $revision );
$helper->setPageLanguage( $language );
$helper->setPageLanguage( 'ar' );
// check nominal content language
$this->assertSame( 'ar', $helper->getHtmlOutputContentLanguage() );

View file

@ -132,7 +132,9 @@ class PageHTMLHandlerTest extends MediaWikiIntegrationTestCase {
$this->getParsoidOutputStash(),
$services->getStatsdDataFactory(),
$parsoidOutputAccess,
$services->getHtmlTransformFactory()
$services->getHtmlTransformFactory(),
$services->getContentHandlerFactory(),
$services->getLanguageFactory()
) );
$handler = new PageHTMLHandler(

View file

@ -131,7 +131,9 @@ class RevisionHTMLHandlerTest extends MediaWikiIntegrationTestCase {
$this->getParsoidOutputStash(),
$services->getStatsdDataFactory(),
$parsoidOutputAccess,
$services->getHtmlTransformFactory()
$services->getHtmlTransformFactory(),
$services->getContentHandlerFactory(),
$services->getLanguageFactory()
) );
$handler = new RevisionHTMLHandler(