From e74ba29aa6b86995a79200fc8b1bb2932d3a1675 Mon Sep 17 00:00:00 2001 From: Brad Jorsch Date: Wed, 22 Nov 2017 15:07:51 -0500 Subject: [PATCH] Use ParserOutput stateless transforms We still set the state in many cases for benefit of extensions, but all calls within core should no longer be using non-default state. Change-Id: I78b62ec33fcb8273acb9b3b4e9012215442be94c Depends-On: I140ff32373430b61b92226689ef9b58cca317450 --- includes/EditPage.php | 5 +++- includes/Message.php | 4 ++- includes/OutputPage.php | 30 ++++++++++++++++------ includes/Status.php | 4 ++- includes/api/ApiParse.php | 9 +++---- includes/content/WikiTextStructure.php | 7 ++--- includes/diff/DifferenceEngine.php | 5 +++- includes/installer/Installer.php | 4 ++- includes/page/Article.php | 19 +++++++++++--- includes/parser/ParserOutput.php | 10 ++++++-- includes/specials/SpecialRecentchanges.php | 4 ++- includes/specials/SpecialUndelete.php | 4 ++- tests/parser/ParserTestRunner.php | 5 ++-- 13 files changed, 80 insertions(+), 30 deletions(-) diff --git a/includes/EditPage.php b/includes/EditPage.php index ff224c5598..bcaab3a3d7 100644 --- a/includes/EditPage.php +++ b/includes/EditPage.php @@ -4012,7 +4012,10 @@ class EditPage { $parserOutput->setEditSectionTokens( false ); // no section edit links return [ 'parserOutput' => $parserOutput, - 'html' => $parserOutput->getText() ]; + 'html' => $parserOutput->getText( [ + 'enableSectionEditLinks' => false + ] ) + ]; } /** diff --git a/includes/Message.php b/includes/Message.php index 3b2f3ccc7b..16ae839e82 100644 --- a/includes/Message.php +++ b/includes/Message.php @@ -1244,7 +1244,9 @@ class Message implements MessageSpecifier, Serializable { $this->getLanguage() ); - return $out instanceof ParserOutput ? $out->getText() : $out; + return $out instanceof ParserOutput + ? $out->getText( [ 'enableSectionEditLinks' => false ] ) + : $out; } /** diff --git a/includes/OutputPage.php b/includes/OutputPage.php index a5f9c18151..92963fd18b 100644 --- a/includes/OutputPage.php +++ b/includes/OutputPage.php @@ -1783,7 +1783,9 @@ class OutputPage extends ContextSource { $popts->setTidy( $oldTidy ); - $this->addParserOutput( $parserOutput ); + $this->addParserOutput( $parserOutput, [ + 'enableSectionEditLinks' => false, + ] ); } /** @@ -1868,9 +1870,10 @@ class OutputPage extends ContextSource { * * @since 1.24 * @param ParserOutput $parserOutput + * @param array $poOptions Options to ParserOutput::getText() */ - public function addParserOutputContent( $parserOutput ) { - $this->addParserOutputText( $parserOutput ); + public function addParserOutputContent( $parserOutput, $poOptions = [] ) { + $this->addParserOutputText( $parserOutput, $poOptions ); $this->addModules( $parserOutput->getModules() ); $this->addModuleScripts( $parserOutput->getModuleScripts() ); @@ -1884,9 +1887,10 @@ class OutputPage extends ContextSource { * * @since 1.24 * @param ParserOutput $parserOutput + * @param array $poOptions Options to ParserOutput::getText() */ - public function addParserOutputText( $parserOutput ) { - $text = $parserOutput->getText(); + public function addParserOutputText( $parserOutput, $poOptions = [] ) { + $text = $parserOutput->getText( $poOptions ); // Avoid PHP 7.1 warning of passing $this by reference $outputPage = $this; Hooks::runWithoutAbort( 'OutputPageBeforeHTML', [ &$outputPage, &$text ] ); @@ -1897,16 +1901,22 @@ class OutputPage extends ContextSource { * Add everything from a ParserOutput object. * * @param ParserOutput $parserOutput + * @param array $poOptions Options to ParserOutput::getText() */ - function addParserOutput( $parserOutput ) { + function addParserOutput( $parserOutput, $poOptions = [] ) { $this->addParserOutputMetadata( $parserOutput ); // Touch section edit links only if not previously disabled if ( $parserOutput->getEditSectionTokens() ) { $parserOutput->setEditSectionTokens( $this->mEnableSectionEditLinks ); } + if ( !$this->mEnableSectionEditLinks + && !array_key_exists( 'enableSectionEditLinks', $poOptions ) + ) { + $poOptions['enableSectionEditLinks'] = false; + } - $this->addParserOutputText( $parserOutput ); + $this->addParserOutputText( $parserOutput, $poOptions ); } /** @@ -1957,7 +1967,9 @@ class OutputPage extends ContextSource { $popts->setTargetLanguage( $oldLang ); } - return $parserOutput->getText(); + return $parserOutput->getText( [ + 'enableSectionEditLinks' => false, + ] ); } /** @@ -3957,6 +3969,7 @@ class OutputPage extends ContextSource { * Enables/disables section edit links, doesn't override __NOEDITSECTION__ * @param bool $flag * @since 1.23 + * @deprecated since 1.31, use $poOptions to addParserOutput() instead. */ public function enableSectionEditLinks( $flag = true ) { $this->mEnableSectionEditLinks = $flag; @@ -3965,6 +3978,7 @@ class OutputPage extends ContextSource { /** * @return bool * @since 1.23 + * @deprecated since 1.31, use $poOptions to addParserOutput() instead. */ public function sectionEditLinksEnabled() { return $this->mEnableSectionEditLinks; diff --git a/includes/Status.php b/includes/Status.php index a35af6e8c6..f17f173edc 100644 --- a/includes/Status.php +++ b/includes/Status.php @@ -316,7 +316,9 @@ class Status extends StatusValue { $lang = $this->languageFromParam( $lang ); $text = $this->getWikiText( $shortContext, $longContext, $lang ); $out = MessageCache::singleton()->parse( $text, null, true, true, $lang ); - return $out instanceof ParserOutput ? $out->getText() : $out; + return $out instanceof ParserOutput + ? $out->getText( [ 'enableSectionEditLinks' => false ] ) + : $out; } /** diff --git a/includes/api/ApiParse.php b/includes/api/ApiParse.php index 15b94fb952..ec015da712 100644 --- a/includes/api/ApiParse.php +++ b/includes/api/ApiParse.php @@ -288,10 +288,6 @@ class ApiParse extends ApiBase { $result_array['textsuppressed'] = true; } - if ( $params['disabletoc'] ) { - $p_result->setTOCEnabled( false ); - } - if ( isset( $params['useskin'] ) ) { $factory = MediaWikiServices::getInstance()->getSkinFactory(); $skin = $factory->makeSkin( Skin::normalizeKey( $params['useskin'] ) ); @@ -347,7 +343,10 @@ class ApiParse extends ApiBase { } if ( isset( $prop['text'] ) ) { - $result_array['text'] = $p_result->getText(); + $result_array['text'] = $p_result->getText( [ + 'allowTOC' => !$params['disabletoc'], + 'enableSectionEditLinks' => !$params['disableeditsection'], + ] ); $result_array[ApiResult::META_BC_SUBELEMENTS][] = 'text'; } diff --git a/includes/content/WikiTextStructure.php b/includes/content/WikiTextStructure.php index aeb96b6531..0eadc3c67a 100644 --- a/includes/content/WikiTextStructure.php +++ b/includes/content/WikiTextStructure.php @@ -146,9 +146,10 @@ class WikiTextStructure { if ( !is_null( $this->allText ) ) { return; } - $this->parserOutput->setEditSectionTokens( false ); - $this->parserOutput->setTOCEnabled( false ); - $text = $this->parserOutput->getText(); + $text = $this->parserOutput->getText( [ + 'enableSectionEditTokens' => false, + 'allowTOC' => false, + ] ); if ( strlen( $text ) == 0 ) { $this->allText = ""; // empty text - nothing to seek here diff --git a/includes/diff/DifferenceEngine.php b/includes/diff/DifferenceEngine.php index 51b9f15a60..7e05be6675 100644 --- a/includes/diff/DifferenceEngine.php +++ b/includes/diff/DifferenceEngine.php @@ -634,7 +634,10 @@ class DifferenceEngine extends ContextSource { if ( Hooks::run( 'DifferenceEngineRenderRevisionAddParserOutput', [ $this, $out, $parserOutput, $wikiPage ] ) ) { - $out->addParserOutput( $parserOutput ); + $out->addParserOutput( $parserOutput, [ + 'enableSectionEditLinks' => $this->mNewRev->isCurrent() + && $this->mNewRev->getTitle()->quickUserCan( 'edit', $this->getUser() ), + ] ); } } } diff --git a/includes/installer/Installer.php b/includes/installer/Installer.php index 2906a83bf4..46978e1ba1 100644 --- a/includes/installer/Installer.php +++ b/includes/installer/Installer.php @@ -688,7 +688,9 @@ abstract class Installer { try { $out = $wgParser->parse( $text, $this->parserTitle, $this->parserOptions, $lineStart ); - $html = $out->getText(); + $html = $out->getText( [ + 'enableSectionEditLinks' => false, + ] ); } catch ( MediaWiki\Services\ServiceDisabledException $e ) { $html = ' ' . htmlspecialchars( $text ); diff --git a/includes/page/Article.php b/includes/page/Article.php index c9dc273b47..dadf311da0 100644 --- a/includes/page/Article.php +++ b/includes/page/Article.php @@ -75,6 +75,13 @@ class Article implements Page { /** @var ParserOutput */ public $mParserOutput; + /** + * @var bool Whether render() was called. With the way subclasses work + * here, there doesn't seem to be any other way to stop calling + * OutputPage::enableSectionEditLinks() and still have it work as it did before. + */ + private $disableSectionEditForRender = false; + /** * Constructor and clear the article * @param Title $title Reference to a Title object. @@ -469,12 +476,17 @@ class Article implements Page { $parserCache = MediaWikiServices::getInstance()->getParserCache(); $parserOptions = $this->getParserOptions(); + $poOptions = []; # Render printable version, use printable version cache if ( $outputPage->isPrintable() ) { $parserOptions->setIsPrintable( true ); $parserOptions->setEditSection( false ); - } elseif ( !$this->isCurrent() || !$this->getTitle()->quickUserCan( 'edit', $user ) ) { + $poOptions['enableSectionEditLinks'] = false; + } elseif ( $this->disableSectionEditForRender + || !$this->isCurrent() || !$this->getTitle()->quickUserCan( 'edit', $user ) + ) { $parserOptions->setEditSection( false ); + $poOptions['enableSectionEditLinks'] = false; } # Try client and file cache @@ -533,7 +545,7 @@ class Article implements Page { } else { wfDebug( __METHOD__ . ": showing parser cache contents\n" ); } - $outputPage->addParserOutput( $this->mParserOutput ); + $outputPage->addParserOutput( $this->mParserOutput, $poOptions ); # Ensure that UI elements requiring revision ID have # the correct version information. $outputPage->setRevisionId( $this->mPage->getLatest() ); @@ -597,7 +609,7 @@ class Article implements Page { } $this->mParserOutput = $poolArticleView->getParserOutput(); - $outputPage->addParserOutput( $this->mParserOutput ); + $outputPage->addParserOutput( $this->mParserOutput, $poOptions ); if ( $content->getRedirectTarget() ) { $outputPage->addSubtitle( "" . $this->getContext()->msg( 'redirectpagesub' )->parse() . "" ); @@ -1515,6 +1527,7 @@ class Article implements Page { $this->getContext()->getRequest()->response()->header( 'X-Robots-Tag: noindex' ); $this->getContext()->getOutput()->setArticleBodyOnly( true ); $this->getContext()->getOutput()->enableSectionEditLinks( false ); + $this->disableSectionEditForRender = true; $this->view(); } diff --git a/includes/parser/ParserOutput.php b/includes/parser/ParserOutput.php index 59c27e5db1..ff9c28d2bb 100644 --- a/includes/parser/ParserOutput.php +++ b/includes/parser/ParserOutput.php @@ -22,6 +22,12 @@ * @ingroup Parser */ class ParserOutput extends CacheTime { + /** + * Feature flag to indicate to extensions that MediaWiki core supports and + * uses getText() stateless transforms. + */ + const SUPPORTS_STATELESS_TRANSFORMS = 1; + /** * @var string $mText The output text */ @@ -147,7 +153,7 @@ class ParserOutput extends CacheTime { * @deprecated since 1.31 Use getText() options. * @var bool $mEditSectionTokens prefix/suffix markers if edit sections were output as tokens. */ - public $mEditSectionTokens = false; + public $mEditSectionTokens = true; /** * @var array $mProperties Name/value pairs to be cached in the DB. @@ -269,7 +275,7 @@ class ParserOutput extends CacheTime { // @todo Warn if !array_key_exists( 'enableSectionEditLinks', $options ) // && !$this->mEditSectionTokens - // Note that while $this->mEditSectionTokens defaults to false, + // Note that while $this->mEditSectionTokens formerly defaulted to false, // ParserOptions->getEditSection() defaults to true and Parser copies // that to us so true makes more sense as the stateless default. diff --git a/includes/specials/SpecialRecentchanges.php b/includes/specials/SpecialRecentchanges.php index dfa13b6cd7..cfc7a85c88 100644 --- a/includes/specials/SpecialRecentchanges.php +++ b/includes/specials/SpecialRecentchanges.php @@ -608,7 +608,9 @@ class SpecialRecentChanges extends ChangesListSpecialPage { /*interface*/false, $wgContLang ); - $content = $parserOutput->getText(); + $content = $parserOutput->getText( [ + 'enableSectionEditLinks' => false, + ] ); // Add only metadata here (including the language links), text is added below $this->getOutput()->addParserOutputMetadata( $parserOutput ); diff --git a/includes/specials/SpecialUndelete.php b/includes/specials/SpecialUndelete.php index 71dee3d832..0c038c18ab 100644 --- a/includes/specials/SpecialUndelete.php +++ b/includes/specials/SpecialUndelete.php @@ -455,7 +455,9 @@ class SpecialUndelete extends SpecialPage { $popts->setEditSection( false ); $pout = $content->getParserOutput( $this->mTargetObj, $rev->getId(), $popts, true ); - $out->addParserOutput( $pout ); + $out->addParserOutput( $pout, [ + 'enableSectionEditLinks' => false, + ] ); } if ( $isText ) { diff --git a/tests/parser/ParserTestRunner.php b/tests/parser/ParserTestRunner.php index 149ba800f2..44a00a8964 100644 --- a/tests/parser/ParserTestRunner.php +++ b/tests/parser/ParserTestRunner.php @@ -853,8 +853,9 @@ class ParserTestRunner { $out = $parser->getPreloadText( $test['input'], $title, $options ); } else { $output = $parser->parse( $test['input'], $title, $options, true, true, 1337 ); - $output->setTOCEnabled( !isset( $opts['notoc'] ) ); - $out = $output->getText(); + $out = $output->getText( [ + 'allowTOC' => !isset( $opts['notoc'] ) + ] ); if ( isset( $opts['tidy'] ) ) { $out = preg_replace( '/\s+$/', '', $out ); } -- 2.20.1