|
|
|
@ -2,7 +2,6 @@
|
|
|
|
|
|
|
|
|
|
namespace MediaWiki\Rest\Handler;
|
|
|
|
|
|
|
|
|
|
use LanguageCode;
|
|
|
|
|
use LogicException;
|
|
|
|
|
use MediaWiki\MediaWikiServices;
|
|
|
|
|
use MediaWiki\Page\RedirectStore;
|
|
|
|
@ -10,11 +9,8 @@ use MediaWiki\Rest\LocalizedHttpException;
|
|
|
|
|
use MediaWiki\Rest\Response;
|
|
|
|
|
use MediaWiki\Rest\SimpleHandler;
|
|
|
|
|
use MediaWiki\Rest\StringStream;
|
|
|
|
|
use ParserOutput;
|
|
|
|
|
use TitleFormatter;
|
|
|
|
|
use Wikimedia\Assert\Assert;
|
|
|
|
|
use Wikimedia\Parsoid\Utils\ContentUtils;
|
|
|
|
|
use Wikimedia\Parsoid\Utils\DOMUtils;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* A handler that returns Parsoid HTML for the following routes:
|
|
|
|
@ -26,7 +22,7 @@ use Wikimedia\Parsoid\Utils\DOMUtils;
|
|
|
|
|
class PageHTMLHandler extends SimpleHandler {
|
|
|
|
|
use PageRedirectHandlerTrait;
|
|
|
|
|
|
|
|
|
|
/** @var HtmlOutputRendererHelper */
|
|
|
|
|
/** @var HtmlOutputHelper */
|
|
|
|
|
private $htmlHelper;
|
|
|
|
|
|
|
|
|
|
/** @var PageContentHelper */
|
|
|
|
@ -38,6 +34,8 @@ class PageHTMLHandler extends SimpleHandler {
|
|
|
|
|
/** @var RedirectStore */
|
|
|
|
|
private $redirectStore;
|
|
|
|
|
|
|
|
|
|
private PageRestHelperFactory $helperFactory;
|
|
|
|
|
|
|
|
|
|
public function __construct(
|
|
|
|
|
TitleFormatter $titleFormatter,
|
|
|
|
|
RedirectStore $redirectStore,
|
|
|
|
@ -46,6 +44,7 @@ class PageHTMLHandler extends SimpleHandler {
|
|
|
|
|
$this->titleFormatter = $titleFormatter;
|
|
|
|
|
$this->redirectStore = $redirectStore;
|
|
|
|
|
$this->contentHelper = $helperFactory->newPageContentHelper();
|
|
|
|
|
$this->helperFactory = $helperFactory;
|
|
|
|
|
$this->htmlHelper = $helperFactory->newHtmlOutputRendererHelper();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -57,19 +56,23 @@ class PageHTMLHandler extends SimpleHandler {
|
|
|
|
|
$this->contentHelper->init( $user, $this->getValidatedParams() );
|
|
|
|
|
|
|
|
|
|
$page = $this->contentHelper->getPageIdentity();
|
|
|
|
|
$isSystemMessage = $this->contentHelper->useDefaultSystemMessage();
|
|
|
|
|
|
|
|
|
|
if ( $this->contentHelper->useDefaultSystemMessage() ) {
|
|
|
|
|
// We can't use the helper object with system messages.
|
|
|
|
|
// TODO: We should have an implementation of HtmlOutputRendererHelper
|
|
|
|
|
// for system messages in the future.
|
|
|
|
|
// Currently NO OP.
|
|
|
|
|
} elseif ( $page ) {
|
|
|
|
|
$this->htmlHelper->init( $page, $this->getValidatedParams(), $user );
|
|
|
|
|
|
|
|
|
|
$request = $this->getRequest();
|
|
|
|
|
$acceptLanguage = $request->getHeaderLine( 'Accept-Language' ) ?: null;
|
|
|
|
|
if ( $acceptLanguage ) {
|
|
|
|
|
$this->htmlHelper->setVariantConversionLanguage( $acceptLanguage );
|
|
|
|
|
if ( $page ) {
|
|
|
|
|
if ( $isSystemMessage ) {
|
|
|
|
|
$this->htmlHelper = $this->helperFactory->newHtmlMessageOutputHelper();
|
|
|
|
|
$this->htmlHelper->init( $page );
|
|
|
|
|
} else {
|
|
|
|
|
$revision = $this->contentHelper->getTargetRevision();
|
|
|
|
|
// NOTE: We know that $this->htmlHelper is an instance of HtmlOutputRendererHelper
|
|
|
|
|
// because we set it in the constructor.
|
|
|
|
|
$this->htmlHelper->init( $page, $this->getValidatedParams(), $user, $revision );
|
|
|
|
|
|
|
|
|
|
$request = $this->getRequest();
|
|
|
|
|
$acceptLanguage = $request->getHeaderLine( 'Accept-Language' ) ?: null;
|
|
|
|
|
if ( $acceptLanguage ) {
|
|
|
|
|
$this->htmlHelper->setVariantConversionLanguage( $acceptLanguage );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -80,8 +83,7 @@ class PageHTMLHandler extends SimpleHandler {
|
|
|
|
|
*/
|
|
|
|
|
public function run(): Response {
|
|
|
|
|
$this->contentHelper->checkAccess();
|
|
|
|
|
$page = $this->contentHelper->getPage();
|
|
|
|
|
$isSystemMessage = $this->contentHelper->useDefaultSystemMessage();
|
|
|
|
|
$page = $this->contentHelper->getPageIdentity();
|
|
|
|
|
$params = $this->getRequest()->getQueryParams();
|
|
|
|
|
|
|
|
|
|
if ( array_key_exists( 'redirect', $params ) ) {
|
|
|
|
@ -92,30 +94,22 @@ class PageHTMLHandler extends SimpleHandler {
|
|
|
|
|
|
|
|
|
|
// The call to $this->contentHelper->getPage() should not return null if
|
|
|
|
|
// $this->contentHelper->checkAccess() did not throw.
|
|
|
|
|
Assert::invariant(
|
|
|
|
|
$page !== null || $isSystemMessage,
|
|
|
|
|
'Page should be known or be a valid system message page'
|
|
|
|
|
Assert::invariant( $page !== null, 'Page should be known' );
|
|
|
|
|
|
|
|
|
|
$redirectResponse = $this->createRedirectResponseIfNeeded(
|
|
|
|
|
$page,
|
|
|
|
|
$followWikiRedirects,
|
|
|
|
|
$this->contentHelper->getTitleText(),
|
|
|
|
|
$this->titleFormatter,
|
|
|
|
|
$this->redirectStore
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if ( $isSystemMessage ) {
|
|
|
|
|
$parserOutput = $this->getSystemMessageOutput();
|
|
|
|
|
} else {
|
|
|
|
|
'@phan-var \MediaWiki\Page\ExistingPageRecord $page';
|
|
|
|
|
$redirectResponse = $this->createRedirectResponseIfNeeded(
|
|
|
|
|
$page,
|
|
|
|
|
$followWikiRedirects,
|
|
|
|
|
$this->contentHelper->getTitleText(),
|
|
|
|
|
$this->titleFormatter,
|
|
|
|
|
$this->redirectStore
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if ( $redirectResponse !== null ) {
|
|
|
|
|
return $redirectResponse;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$parserOutput = $this->htmlHelper->getHtml();
|
|
|
|
|
if ( $redirectResponse !== null ) {
|
|
|
|
|
return $redirectResponse;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$parserOutput = $this->htmlHelper->getHtml();
|
|
|
|
|
|
|
|
|
|
// Do not de-duplicate styles, Parsoid already does it in a slightly different way (T300325)
|
|
|
|
|
$parserOutputHtml = $parserOutput->getText( [ 'deduplicateStyles' => false ] );
|
|
|
|
|
|
|
|
|
@ -130,17 +124,12 @@ class PageHTMLHandler extends SimpleHandler {
|
|
|
|
|
$body = $this->contentHelper->constructMetadata();
|
|
|
|
|
$body['html'] = $parserOutputHtml;
|
|
|
|
|
|
|
|
|
|
if ( $page ) {
|
|
|
|
|
// If param redirect=no is present, that means this page can be a redirect
|
|
|
|
|
// check for a redirectTargetUrl and send it to the body as `redirect_target`
|
|
|
|
|
'@phan-var \MediaWiki\Page\ExistingPageRecord $page';
|
|
|
|
|
$redirectTargetUrl = $this->getWikiRedirectTargetUrl(
|
|
|
|
|
$page, $this->redirectStore, $this->titleFormatter
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if ( $redirectTargetUrl ) {
|
|
|
|
|
$body['redirect_target'] = $redirectTargetUrl;
|
|
|
|
|
}
|
|
|
|
|
$redirectTargetUrl = $this->getWikiRedirectTargetUrl(
|
|
|
|
|
$page, $this->redirectStore, $this->titleFormatter
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if ( $redirectTargetUrl ) {
|
|
|
|
|
$body['redirect_target'] = $redirectTargetUrl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$response = $this->getResponseFactory()->createJson( $body );
|
|
|
|
@ -150,29 +139,12 @@ class PageHTMLHandler extends SimpleHandler {
|
|
|
|
|
throw new LogicException( "Unknown HTML type $outputMode" );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( !$isSystemMessage ) {
|
|
|
|
|
$setContentLanguageHeader = ( $outputMode === 'html' );
|
|
|
|
|
$this->htmlHelper->putHeaders( $response, $setContentLanguageHeader );
|
|
|
|
|
}
|
|
|
|
|
$setContentLanguageHeader = ( $outputMode === 'html' );
|
|
|
|
|
$this->htmlHelper->putHeaders( $response, $setContentLanguageHeader );
|
|
|
|
|
|
|
|
|
|
return $response;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function getSystemMessageOutput(): ParserOutput {
|
|
|
|
|
$message = $this->contentHelper->getDefaultSystemMessage();
|
|
|
|
|
|
|
|
|
|
$messageDom = DOMUtils::parseHTML( $message->parse() );
|
|
|
|
|
DOMUtils::appendToHead( $messageDom, 'meta', [
|
|
|
|
|
'http-equiv' => 'content-language',
|
|
|
|
|
'content' => LanguageCode::bcp47( $message->getLanguage()->getCode() ),
|
|
|
|
|
] );
|
|
|
|
|
|
|
|
|
|
$messageDocHtml = ContentUtils::toXML( $messageDom );
|
|
|
|
|
|
|
|
|
|
// TODO: Set language in the response headers.
|
|
|
|
|
return new ParserOutput( $messageDocHtml );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns an ETag representing a page's source. The ETag assumes a page's source has changed
|
|
|
|
|
* if the latest revision of a page has been made private, un-readable for another reason,
|
|
|
|
@ -184,13 +156,6 @@ class PageHTMLHandler extends SimpleHandler {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( $this->contentHelper->useDefaultSystemMessage() ) {
|
|
|
|
|
// XXX: We end up generating the HTML twice. Would be nice to avoid that.
|
|
|
|
|
// But messages are small, and not hit a lot...
|
|
|
|
|
$output = $this->getSystemMessageOutput();
|
|
|
|
|
return '"message/' . sha1( $output->getRawText() ) . '/' . $this->getOutputMode() . '"';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Vary eTag based on output mode
|
|
|
|
|
return $this->htmlHelper->getETag( $this->getOutputMode() );
|
|
|
|
|
}
|
|
|
|
@ -203,10 +168,6 @@ class PageHTMLHandler extends SimpleHandler {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( $this->contentHelper->useDefaultSystemMessage() ) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $this->htmlHelper->getLastModified();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|