wiki.techinc.nl/includes/Rest/Handler/RevisionHTMLHandler.php
Derick Alangi 1afd52e3e4 REST: Move Helper classes to their own namespace
Mixing Handlers with Helpers doesn't look nice for consistency
reasons. Helpers should be in their own place (grouped) in the
Handlers directory as they're really "helpers for the handlers".

Change-Id: Ieeb7a0a706a4cb38778f312bfbfe781a1f366d14
2023-01-16 21:16:09 +01:00

151 lines
4.6 KiB
PHP

<?php
namespace MediaWiki\Rest\Handler;
use LogicException;
use MediaWiki\MediaWikiServices;
use MediaWiki\Rest\Handler\Helper\HtmlOutputRendererHelper;
use MediaWiki\Rest\Handler\Helper\PageRestHelperFactory;
use MediaWiki\Rest\Handler\Helper\RevisionContentHelper;
use MediaWiki\Rest\LocalizedHttpException;
use MediaWiki\Rest\Response;
use MediaWiki\Rest\SimpleHandler;
use MediaWiki\Rest\StringStream;
use Wikimedia\Assert\Assert;
/**
* A handler that returns Parsoid HTML for the following routes:
* - /revision/{revision}/html,
* - /revision/{revision}/with_html
*
* Class RevisionHTMLHandler
* @package MediaWiki\Rest\Handler
*/
class RevisionHTMLHandler extends SimpleHandler {
/** @var HtmlOutputRendererHelper */
private $htmlHelper;
/** @var RevisionContentHelper */
private $contentHelper;
public function __construct( PageRestHelperFactory $helperFactory ) {
$this->contentHelper = $helperFactory->newRevisionContentHelper();
$this->htmlHelper = $helperFactory->newHtmlOutputRendererHelper();
}
protected function postValidationSetup() {
// TODO: Once Authority supports rate limit (T310476), just inject the Authority.
$user = MediaWikiServices::getInstance()->getUserFactory()
->newFromUserIdentity( $this->getAuthority()->getUser() );
$this->contentHelper->init( $user, $this->getValidatedParams() );
$page = $this->contentHelper->getPage();
$revision = $this->contentHelper->getTargetRevision();
if ( $page && $revision ) {
$this->htmlHelper->init( $page, $this->getValidatedParams(), $user, $revision );
$request = $this->getRequest();
$acceptLanguage = $request->getHeaderLine( 'Accept-Language' ) ?: null;
if ( $acceptLanguage ) {
$this->htmlHelper->setVariantConversionLanguage( $acceptLanguage );
}
}
}
/**
* @return Response
* @throws LocalizedHttpException
*/
public function run(): Response {
$this->contentHelper->checkAccess();
$page = $this->contentHelper->getPage();
$revisionRecord = $this->contentHelper->getTargetRevision();
// The call to $this->contentHelper->getPage() should not return null if
// $this->contentHelper->checkAccess() did not throw.
Assert::invariant( $page !== null, 'Page should be known' );
// The call to $this->contentHelper->getTargetRevision() should not return null if
// $this->contentHelper->checkAccess() did not throw.
Assert::invariant( $revisionRecord !== null, 'Revision should be known' );
$outputMode = $this->getOutputMode();
$setContentLanguageHeader = true;
switch ( $outputMode ) {
case 'html':
$parserOutput = $this->htmlHelper->getHtml();
$response = $this->getResponseFactory()->create();
// TODO: need to respect content-type returned by Parsoid.
$response->setHeader( 'Content-Type', 'text/html' );
$this->htmlHelper->putHeaders( $response, $setContentLanguageHeader );
$this->contentHelper->setCacheControl( $response, $parserOutput->getCacheExpiry() );
$response->setBody( new StringStream( $parserOutput->getText() ) );
break;
case 'with_html':
$parserOutput = $this->htmlHelper->getHtml();
$body = $this->contentHelper->constructMetadata();
$body['html'] = $parserOutput->getText();
$response = $this->getResponseFactory()->createJson( $body );
// For JSON content, it doesn't make sense to set content language header
$this->htmlHelper->putHeaders( $response, !$setContentLanguageHeader );
$this->contentHelper->setCacheControl( $response, $parserOutput->getCacheExpiry() );
break;
default:
throw new LogicException( "Unknown HTML type $outputMode" );
}
return $response;
}
/**
* 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,
* or a newer revision exists.
* @return string|null
*/
protected function getETag(): ?string {
if ( !$this->contentHelper->isAccessible() ) {
return null;
}
// Vary eTag based on output mode
return $this->htmlHelper->getETag( $this->getOutputMode() );
}
/**
* @return string|null
*/
protected function getLastModified(): ?string {
if ( !$this->contentHelper->isAccessible() ) {
return null;
}
return $this->htmlHelper->getLastModified();
}
private function getOutputMode(): string {
return $this->getConfig()['format'];
}
public function needsWriteAccess(): bool {
return false;
}
public function getParamSettings(): array {
return array_merge(
$this->contentHelper->getParamSettings(),
$this->htmlHelper->getParamSettings()
);
}
/**
* @return bool
*/
protected function hasRepresentation() {
return $this->contentHelper->hasContent();
}
}