Move Content::preloadTransform to ContentHandler

Update ContentTransformer to access ContentHandler::preLoadTransform through the service.
Prepare object to hold a data that required for ContentHandler::preLoadTranform params.

This is a fully backwards compatible change.
We are doing hard deprecation via MWDebug::detectDeprecatedOverride.

However, with the ContentHandler calling Content and
Content calling ContentHandler, it doesn't matter whether
callers use Content or ContentHandler. This will allow us
to naturally convert all callers.

Bug: T287157
Change-Id: I89537e1e7d24c6e15252b2b51890a0bd81ea3e6b
This commit is contained in:
Roman Stolar 2021-08-09 16:39:19 +03:00 committed by Daniel Kinzler
parent 63da9a1430
commit 42442e01ff
14 changed files with 332 additions and 59 deletions

View file

@ -1602,7 +1602,13 @@ class EditPage implements IEditObject {
$content = $converted;
}
return $content->preloadTransform( $title, $parserOptions, $params );
$contentTransformer = MediaWikiServices::getInstance()->getContentTransformer();
return $contentTransformer->preloadTransform(
$content,
$title,
$parserOptions,
$params
);
}
/**

View file

@ -27,6 +27,7 @@
*/
use MediaWiki\Content\IContentHandlerFactory;
use MediaWiki\Content\Transform\PreloadTransformParamsValue;
use MediaWiki\Content\Transform\PreSaveTransformParamsValue;
use MediaWiki\MediaWikiServices;
@ -420,9 +421,9 @@ abstract class AbstractContent implements Content {
}
/**
* @stable to override
* @since 1.21
*
* @deprecated since 1.37. Use ContentTransformer::preloadTransform instead.
* Extensions defining a content model should override ContentHandler::preloadTransform.
* @param Title $title
* @param ParserOptions $popts
* @param array $params
@ -431,7 +432,11 @@ abstract class AbstractContent implements Content {
* @see Content::preloadTransform
*/
public function preloadTransform( Title $title, ParserOptions $popts, $params = [] ) {
return $this;
$pltParams = new PreloadTransformParamsValue( $title, $popts, $params );
return $this->getContentHandler()->preloadTransform(
$this,
$pltParams
);
}
/**

View file

@ -415,7 +415,8 @@ interface Content {
* object if no transformations apply).
*
* @since 1.21
*
* @deprecated since 1.37 Use ContentTransformer::preloadTransform
* and override ContentHandler::preloadTransform.
* @param Title $title
* @param ParserOptions $parserOptions
* @param array $params

View file

@ -26,6 +26,7 @@
* @author Daniel Kinzler
*/
use MediaWiki\Content\Transform\PreloadTransformParams;
use MediaWiki\Content\Transform\PreSaveTransformParams;
use MediaWiki\HookContainer\ProtectedHookAccessorTrait;
use MediaWiki\Logger\LoggerFactory;
@ -1546,37 +1547,117 @@ abstract class ContentHandler {
Content $content,
PreSaveTransformParams $pstParams
): Content {
$deprecatedContent = $this->maybeCallDeprecatedContentPST( $content, $pstParams );
if ( $deprecatedContent ) {
return $deprecatedContent;
$shouldCallDeprecatedMethod = $this->shouldCallDeprecatedContentTransformMethod(
$content,
$pstParams
);
if ( !$shouldCallDeprecatedMethod ) {
return $content;
}
return $content;
return $this->callDeprecatedContentPST(
$content,
$pstParams
);
}
/**
* If provided content overrides deprecated Content::preSaveTransform,
* call it and return. Otherwise return null.
* @internal only core ContentHandler implementations need to call this.
* Returns a $content object with preload transformations applied (or the same
* object if no transformations apply).
*
* @note Not stable to call other then from ContentHandler hierarchy.
* Callers need to use ContentTransformer::preLoadTransform.
* @stable to override
* @since 1.37
*
* @param Content $content
* @param PreSaveTransformParams $pstParams
* @return ?Content
* @param PreloadTransformParams $pltParams
*
* @return Content
*/
protected function maybeCallDeprecatedContentPST(
public function preloadTransform(
Content $content,
PreSaveTransformParams $pstParams
): ?Content {
$contentOverridesTransform = MWDebug::detectDeprecatedOverride(
PreloadTransformParams $pltParams
): Content {
$shouldCallDeprecatedMethod = $this->shouldCallDeprecatedContentTransformMethod(
$content,
$pltParams
);
if ( !$shouldCallDeprecatedMethod ) {
return $content;
}
return $this->callDeprecatedContentPLT(
$content,
$pltParams
);
}
/**
* Check if we need to provide content overrides deprecated Content method.
*
* @internal only core ContentHandler implementations need to call this.
* @param Content $content
* @param PreSaveTransformParams|PreloadTransformParams $params
* @return bool
*/
protected function shouldCallDeprecatedContentTransformMethod(
Content $content,
$params
): bool {
$method = $params instanceof PreSaveTransformParams
? "preSaveTransform"
: "preloadTransform";
return MWDebug::detectDeprecatedOverride(
$content,
AbstractContent::class,
'preSaveTransform'
$method
);
}
/**
* Provided content overrides deprecated Content::preSaveTransform,
* call it and return.
* @internal only core ContentHandler implementations need to call this.
* @param Content $content
* @param PreSaveTransformParams $params
* @return Content
*/
protected function callDeprecatedContentPST(
Content $content,
PreSaveTransformParams $params
): Content {
$services = MediaWikiServices::getInstance();
$legacyUser = $services->getUserFactory()->newFromUserIdentity( $params->getUser() );
$legacyTitle = $services->getTitleFactory()->castFromPageReference( $params->getPage() );
return $content->preSaveTransform(
$legacyTitle,
$legacyUser,
$params->getParserOptions()
);
}
/**
* If provided content overrides deprecated Content::preloadTransform,
* call it and return.
* @internal only core ContentHandler implementations need to call this.
* @param Content $content
* @param PreloadTransformParams $params
* @return Content
*/
protected function callDeprecatedContentPLT(
Content $content,
PreloadTransformParams $params
): Content {
$services = MediaWikiServices::getInstance();
$legacyTitle = $services->getTitleFactory()->castFromPageReference( $params->getPage() );
return $content->preloadTransform(
$legacyTitle,
$params->getParserOptions(),
$params->getParams()
);
if ( $contentOverridesTransform ) {
$services = MediaWikiServices::getInstance();
$legacyUser = $services->getUserFactory()->newFromUserIdentity( $pstParams->getUser() );
$legacyTitle = $services->getTitleFactory()->castFromPageReference( $pstParams->getPage() );
return $content->preSaveTransform( $legacyTitle, $legacyUser, $pstParams->getParserOptions() );
}
return null;
}
}

View file

@ -66,9 +66,16 @@ class CssContentHandler extends CodeContentHandler {
Content $content,
PreSaveTransformParams $pstParams
): Content {
$deprecatedContent = $this->maybeCallDeprecatedContentPST( $content, $pstParams );
if ( $deprecatedContent ) {
return $deprecatedContent;
$shouldCallDeprecatedMethod = $this->shouldCallDeprecatedContentTransformMethod(
$content,
$pstParams
);
if ( $shouldCallDeprecatedMethod ) {
return $this->callDeprecatedContentPST(
$content,
$pstParams
);
}
'@phan-var CssContent $content';

View file

@ -67,9 +67,16 @@ class JavaScriptContentHandler extends CodeContentHandler {
Content $content,
PreSaveTransformParams $pstParams
): Content {
$deprecatedContent = $this->maybeCallDeprecatedContentPST( $content, $pstParams );
if ( $deprecatedContent ) {
return $deprecatedContent;
$shouldCallDeprecatedMethod = $this->shouldCallDeprecatedContentTransformMethod(
$content,
$pstParams
);
if ( $shouldCallDeprecatedMethod ) {
return $this->callDeprecatedContentPST(
$content,
$pstParams
);
}
'@phan-var JavascriptContent $content';

View file

@ -51,9 +51,16 @@ class JsonContentHandler extends CodeContentHandler {
Content $content,
PreSaveTransformParams $pstParams
): Content {
$deprecatedContent = $this->maybeCallDeprecatedContentPST( $content, $pstParams );
if ( $deprecatedContent ) {
return $deprecatedContent;
$shouldCallDeprecatedMethod = $this->shouldCallDeprecatedContentTransformMethod(
$content,
$pstParams
);
if ( $shouldCallDeprecatedMethod ) {
return $this->callDeprecatedContentPST(
$content,
$pstParams
);
}
'@phan-var JsonContent $content';

View file

@ -166,9 +166,16 @@ class TextContentHandler extends ContentHandler {
Content $content,
PreSaveTransformParams $pstParams
): Content {
$deprecatedContent = $this->maybeCallDeprecatedContentPST( $content, $pstParams );
if ( $deprecatedContent ) {
return $deprecatedContent;
$shouldCallDeprecatedMethod = $this->shouldCallDeprecatedContentTransformMethod(
$content,
$pstParams
);
if ( $shouldCallDeprecatedMethod ) {
return $this->callDeprecatedContentPST(
$content,
$pstParams
);
}
'@phan-var TextContent $content';

View file

@ -45,4 +45,27 @@ class ContentTransformer {
return $contentHandler->preSaveTransform( $content, $pstParams );
}
/**
* Returns a Content object with preload transformations applied (or $content
* if no transformations apply).
*
* @param Content $content
* @param PageReference $page
* @param ParserOptions $parserOptions
* @param array $params
*
* @return Content
*/
public function preloadTransform(
Content $content,
PageReference $page,
ParserOptions $parserOptions,
array $params = []
): Content {
$contentHandler = $this->contentHandlerFactory->getContentHandler( $content->getModel() );
$pltParams = new PreloadTransformParamsValue( $page, $parserOptions, $params );
return $contentHandler->preloadTransform( $content, $pltParams );
}
}

View file

@ -0,0 +1,27 @@
<?php
namespace MediaWiki\Content\Transform;
use MediaWiki\Page\PageReference;
use ParserOptions;
/**
* @since 1.37
* An interface to hold pre-load transform params.
*/
interface PreloadTransformParams {
/**
* @return PageReference
*/
public function getPage(): PageReference;
/**
* @return array
*/
public function getParams(): array;
/**
* @return ParserOptions
*/
public function getParserOptions(): ParserOptions;
}

View file

@ -0,0 +1,50 @@
<?php
namespace MediaWiki\Content\Transform;
use MediaWiki\Page\PageReference;
use ParserOptions;
/**
* @internal
* An object to hold preload transform params.
*/
class PreloadTransformParamsValue implements PreloadTransformParams {
/** @var PageReference */
private $page;
/** @var array */
private $params;
/** @var ParserOptions */
private $parserOptions;
public function __construct( PageReference $page, ParserOptions $parserOptions, array $params = [] ) {
$this->page = $page;
$this->parserOptions = $parserOptions;
$this->params = $params;
}
/**
*
* @return PageReference
*/
public function getPage(): PageReference {
return $this->page;
}
/**
*
* @return array
*/
public function getParams(): array {
return $this->params;
}
/**
*
* @return ParserOptions
*/
public function getParserOptions(): ParserOptions {
return $this->parserOptions;
}
}

View file

@ -141,24 +141,6 @@ class WikitextContent extends TextContent {
return new static( $text );
}
/**
* Returns a Content object with preload transformations applied (or this
* object if no transformations apply).
*
* @param Title $title
* @param ParserOptions $popts
* @param array $params
*
* @return Content
*/
public function preloadTransform( Title $title, ParserOptions $popts, $params = [] ) {
$text = $this->getText();
$plt = MediaWikiServices::getInstance()->getParser()
->getPreloadText( $text, $title, $popts, $params );
return new static( $plt );
}
/**
* Extract the redirect target and the remaining text on the page.
*

View file

@ -23,6 +23,7 @@
* @ingroup Content
*/
use MediaWiki\Content\Transform\PreloadTransformParams;
use MediaWiki\Content\Transform\PreSaveTransformParams;
use MediaWiki\Languages\LanguageNameUtils;
use MediaWiki\MediaWikiServices;
@ -193,9 +194,16 @@ class WikitextContentHandler extends TextContentHandler {
Content $content,
PreSaveTransformParams $pstParams
): Content {
$deprecatedContent = $this->maybeCallDeprecatedContentPST( $content, $pstParams );
if ( $deprecatedContent ) {
return $deprecatedContent;
$shouldCallDeprecatedMethod = $this->shouldCallDeprecatedContentTransformMethod(
$content,
$pstParams
);
if ( $shouldCallDeprecatedMethod ) {
return $this->callDeprecatedContentPST(
$content,
$pstParams
);
}
'@phan-var WikitextContent $content';
@ -219,4 +227,43 @@ class WikitextContentHandler extends TextContentHandler {
$ret->setPreSaveTransformFlags( $parser->getOutput()->getAllFlags() );
return $ret;
}
/**
* Returns a Content object with preload transformations applied (or this
* object if no transformations apply).
*
* @param Content $content
* @param PreloadTransformParams $pltParams
*
* @return Content
*/
public function preloadTransform(
Content $content,
PreloadTransformParams $pltParams
): Content {
$shouldCallDeprecatedMethod = $this->shouldCallDeprecatedContentTransformMethod(
$content,
$pltParams
);
if ( $shouldCallDeprecatedMethod ) {
return $this->callDeprecatedContentPLT(
$content,
$pltParams
);
}
'@phan-var WikitextContent $content';
$text = $content->getText();
$plt = MediaWikiServices::getInstance()->getParser()->getPreloadText(
$text,
$pltParams->getPage(),
$pltParams->getParserOptions(),
$pltParams->getParams()
);
$contentClass = $this->getContentClass();
return new $contentClass( $plt );
}
}

View file

@ -28,4 +28,27 @@ class ContentTransformerTest extends MediaWikiIntegrationTestCase {
$newContent = $services->getContentTransformer()->preSaveTransform( $content, $title, $user, $options );
$this->assertSame( $expectedContainText, $newContent->serialize() );
}
public function preloadTransformProvider() {
return [
[
new WikitextContent( '{{Foo}}<noinclude> censored</noinclude> information <!-- is very secret -->' ),
'{{Foo}} information <!-- is very secret -->'
],
];
}
/**
* @covers MediaWiki\Content\Transform\ContentTransformer::preloadTransform
*
* @dataProvider preloadTransformProvider
*/
public function testPreloadTransform( $content, $expectedContainText ) {
$services = MediaWikiServices::getInstance();
$title = Title::newFromText( 'Test' );
$options = ParserOptions::newFromAnon();
$newContent = $services->getContentTransformer()->preloadTransform( $content, $title, $options );
$this->assertSame( $expectedContainText, $newContent->serialize() );
}
}