jenkins-bot has submitted this change and it was merged. ( https://gerrit.wikimedia.org/r/393260 )
Change subject: ParserOutput: Add stateless transforms to getText() ...................................................................... ParserOutput: Add stateless transforms to getText() The stateful transforms are deprecated. Inspired by Krinkle's If2fb32fc. Bug: T171797 Change-Id: Ied5fe1a6159c2d4fa48170042b44d735ce7b6f9b --- M RELEASE-NOTES-1.31 M docs/hooks.txt M includes/parser/ParserOptions.php M includes/parser/ParserOutput.php M tests/phpunit/includes/parser/ParserOutputTest.php 5 files changed, 298 insertions(+), 4 deletions(-) Approvals: Legoktm: Looks good to me, approved jenkins-bot: Verified diff --git a/RELEASE-NOTES-1.31 b/RELEASE-NOTES-1.31 index b32e3e7..139773b 100644 --- a/RELEASE-NOTES-1.31 +++ b/RELEASE-NOTES-1.31 @@ -31,6 +31,8 @@ [[iw:User:Example|iw>Example]]. * (T111605) The 'ImportHandleUnknownUser' hook allows extensions to auto-create users during an import. +* Added a hook, ParserOutputPostCacheTransform, to allow extensions to affect + the ParserOutput::getText() post-cache transformations. === External library changes in 1.31 === @@ -119,6 +121,18 @@ * The Block class will no longer accept usable-but-missing usernames for 'byText' or ->setBlocker(). Callers should either ensure the blocker exists locally or use a new interwiki-format username like "iw>Example". +* The following methods that get and set ParserOutput state are deprecated. + Callers should use the new stateless $options parameter to + ParserOutput::getText() instead. + * ParserOptions::getEditSection() + * ParserOptions::setEditSection() + * ParserOutput::getEditSectionTokens() + * ParserOutput::setEditSectionTokens() + * ParserOutput::getTOCEnabled() + * ParserOutput::setTOCEnabled() + * OutputPage::enableSectionEditLinks() + * OutputPage::sectionEditLinksEnabled() + * The public ParserOutput state fields $mTOCEnabled and $mEditSectionTokens are also deprecated. == Compatibility == MediaWiki 1.31 requires PHP 5.5.9 or later. There is experimental support for diff --git a/docs/hooks.txt b/docs/hooks.txt index 685a182..29883b2 100644 --- a/docs/hooks.txt +++ b/docs/hooks.txt @@ -2594,6 +2594,12 @@ callable here. The callable is passed the ParserOptions object and the option name. +'ParserOutputPostCacheTransform': Called from ParserOutput::getText() to do +post-cache transforms. +$parserOutput: The ParserOutput object. +&$text: The text being transformed, before core transformations are done. +&$options: The options array being used for the transformation. + 'ParserSectionCreate': Called each time the parser creates a document section from wikitext. Use this to apply per-section modifications to HTML (like wrapping the section in a DIV). Caveat: DIVs are valid wikitext, and a DIV diff --git a/includes/parser/ParserOptions.php b/includes/parser/ParserOptions.php index 5e2845f..f99089b 100644 --- a/includes/parser/ParserOptions.php +++ b/includes/parser/ParserOptions.php @@ -869,6 +869,7 @@ /** * Create "edit section" links? + * @deprecated since 1.31, use ParserOutput::getText() options instead. * @return bool */ public function getEditSection() { @@ -877,6 +878,7 @@ /** * Create "edit section" links? + * @deprecated since 1.31, use ParserOutput::getText() options instead. * @param bool|null $x New value (null is no change) * @return bool Old value */ diff --git a/includes/parser/ParserOutput.php b/includes/parser/ParserOutput.php index 3480a51..59c27e5 100644 --- a/includes/parser/ParserOutput.php +++ b/includes/parser/ParserOutput.php @@ -144,6 +144,7 @@ public $mSections = []; /** + * @deprecated since 1.31 Use getText() options. * @var bool $mEditSectionTokens prefix/suffix markers if edit sections were output as tokens. */ public $mEditSectionTokens = false; @@ -164,6 +165,7 @@ public $mTimestamp; /** + * @deprecated since 1.31 Use getText() options. * @var bool $mTOCEnabled Whether TOC should be shown, can't override __NOTOC__. */ public $mTOCEnabled = true; @@ -250,9 +252,38 @@ return $this->mText; } - public function getText() { + /** + * Get the output HTML + * + * @param array $options (since 1.31) Transformations to apply to the HTML + * - allowTOC: (bool) Show the TOC, assuming there were enough headings + * to generate one and `__NOTOC__` wasn't used. Default is true, + * but might be statefully overridden. + * - enableSectionEditLinks: (bool) Include section edit links, assuming + * section edit link tokens are present in the HTML. Default is true, + * but might be statefully overridden. + * @return string HTML + */ + public function getText( $options = [] ) { + // @todo Warn if !array_key_exists( 'allowTOC', $options ) && empty( $this->mTOCEnabled ) + + // @todo Warn if !array_key_exists( 'enableSectionEditLinks', $options ) + // && !$this->mEditSectionTokens + // Note that while $this->mEditSectionTokens defaults to false, + // ParserOptions->getEditSection() defaults to true and Parser copies + // that to us so true makes more sense as the stateless default. + + $options += [ + // empty() here because old cached versions might lack the field somehow. + // In that situation, the historical behavior (possibly buggy) is to remove the TOC. + 'allowTOC' => !empty( $this->mTOCEnabled ), + 'enableSectionEditLinks' => $this->mEditSectionTokens, + ]; $text = $this->mText; - if ( $this->mEditSectionTokens ) { + + Hooks::runWithoutAbort( 'ParserOutputPostCacheTransform', [ $this, &$text, &$options ] ); + + if ( $options['enableSectionEditLinks'] ) { $text = preg_replace_callback( self::EDITSECTION_REGEX, function ( $m ) { @@ -278,8 +309,7 @@ $text = preg_replace( self::EDITSECTION_REGEX, '', $text ); } - // If you have an old cached version of this class - sorry, you can't disable the TOC - if ( isset( $this->mTOCEnabled ) && $this->mTOCEnabled ) { + if ( $options['allowTOC'] ) { $text = str_replace( [ Parser::TOC_START, Parser::TOC_END ], '', $text ); } else { $text = preg_replace( @@ -288,6 +318,7 @@ $text ); } + return $text; } @@ -339,6 +370,9 @@ return $this->mSections; } + /** + * @deprecated since 1.31 Use getText() options. + */ public function getEditSectionTokens() { return $this->mEditSectionTokens; } @@ -426,6 +460,9 @@ return $this->mLimitReportJSData; } + /** + * @deprecated since 1.31 Use getText() options. + */ public function getTOCEnabled() { return $this->mTOCEnabled; } @@ -454,6 +491,9 @@ return wfSetVar( $this->mSections, $toc ); } + /** + * @deprecated since 1.31 Use getText() options. + */ public function setEditSectionTokens( $t ) { return wfSetVar( $this->mEditSectionTokens, $t ); } @@ -470,6 +510,9 @@ return wfSetVar( $this->mTimestamp, $timestamp ); } + /** + * @deprecated since 1.31 Use getText() options. + */ public function setTOCEnabled( $flag ) { return wfSetVar( $this->mTOCEnabled, $flag ); } diff --git a/tests/phpunit/includes/parser/ParserOutputTest.php b/tests/phpunit/includes/parser/ParserOutputTest.php index ec8f0d0..441d60d 100644 --- a/tests/phpunit/includes/parser/ParserOutputTest.php +++ b/tests/phpunit/includes/parser/ParserOutputTest.php @@ -1,5 +1,7 @@ <?php +use Wikimedia\TestingAccessWrapper; + /** * @group Database * ^--- trigger DB shadowing because we are using Title magic @@ -89,4 +91,231 @@ $this->assertArrayNotHasKey( 'foo', $properties ); } + /** + * @covers ParserOutput::getText + * @dataProvider provideGetText + * @param array $options Options to getText() + * @param array $poState ParserOptions state fields to set + * @param string $text Parser text + * @param string $expect Expected output + */ + public function testGetText( $options, $poState, $text, $expect ) { + $this->setMwGlobals( [ + 'wgArticlePath' => '/wiki/$1', + 'wgScriptPath' => '/w', + 'wgScript' => '/w/index.php', + ] ); + + $po = new ParserOutput( $text ); + + // Emulate Parser + $po->setEditSectionTokens( true ); + + if ( $poState ) { + $wrap = TestingAccessWrapper::newFromObject( $po ); + foreach ( $poState as $key => $value ) { + $wrap->$key = $value; + } + } + + $actual = $po->getText( $options ); + $this->assertSame( $expect, $actual ); + } + + public static function provideGetText() { + // @codingStandardsIgnoreStart Generic.Files.LineLength + $text = <<<EOF +<p>Test document. +</p> +<mw:toc><div id="toc" class="toc"><div class="toctitle"><h2>Contents</h2></div> +<ul> +<li class="toclevel-1 tocsection-1"><a href="#Section_1"><span class="tocnumber">1</span> <span class="toctext">Section 1</span></a></li> +<li class="toclevel-1 tocsection-2"><a href="#Section_2"><span class="tocnumber">2</span> <span class="toctext">Section 2</span></a> +<ul> +<li class="toclevel-2 tocsection-3"><a href="#Section_2.1"><span class="tocnumber">2.1</span> <span class="toctext">Section 2.1</span></a></li> +</ul> +</li> +<li class="toclevel-1 tocsection-4"><a href="#Section_3"><span class="tocnumber">3</span> <span class="toctext">Section 3</span></a></li> +</ul> +</div> +</mw:toc> +<h2><span class="mw-headline" id="Section_1">Section 1</span><mw:editsection page="Test Page" section="1">Section 1</mw:editsection></h2> +<p>One +</p> +<h2><span class="mw-headline" id="Section_2">Section 2</span><mw:editsection page="Test Page" section="2">Section 2</mw:editsection></h2> +<p>Two +</p> +<h3><span class="mw-headline" id="Section_2.1">Section 2.1</span><mw:editsection page="Test Page" section="3">Section 2.1</mw:editsection></h3> +<p>Two point one +</p> +<h2><span class="mw-headline" id="Section_3">Section 3</span><mw:editsection page="Test Page" section="4">Section 3</mw:editsection></h2> +<p>Three +</p> +EOF; + + return [ + 'No stateless options, default state' => [ + [], [], $text, <<<EOF +<p>Test document. +</p> +<div id="toc" class="toc"><div class="toctitle"><h2>Contents</h2></div> +<ul> +<li class="toclevel-1 tocsection-1"><a href="#Section_1"><span class="tocnumber">1</span> <span class="toctext">Section 1</span></a></li> +<li class="toclevel-1 tocsection-2"><a href="#Section_2"><span class="tocnumber">2</span> <span class="toctext">Section 2</span></a> +<ul> +<li class="toclevel-2 tocsection-3"><a href="#Section_2.1"><span class="tocnumber">2.1</span> <span class="toctext">Section 2.1</span></a></li> +</ul> +</li> +<li class="toclevel-1 tocsection-4"><a href="#Section_3"><span class="tocnumber">3</span> <span class="toctext">Section 3</span></a></li> +</ul> +</div> + +<h2><span class="mw-headline" id="Section_1">Section 1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&action=edit&section=1" title="Edit section: Section 1">edit</a><span class="mw-editsection-bracket">]</span></span></h2> +<p>One +</p> +<h2><span class="mw-headline" id="Section_2">Section 2</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&action=edit&section=2" title="Edit section: Section 2">edit</a><span class="mw-editsection-bracket">]</span></span></h2> +<p>Two +</p> +<h3><span class="mw-headline" id="Section_2.1">Section 2.1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&action=edit&section=3" title="Edit section: Section 2.1">edit</a><span class="mw-editsection-bracket">]</span></span></h3> +<p>Two point one +</p> +<h2><span class="mw-headline" id="Section_3">Section 3</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&action=edit&section=4" title="Edit section: Section 3">edit</a><span class="mw-editsection-bracket">]</span></span></h2> +<p>Three +</p> +EOF + ], + 'No stateless options, TOC statefully disabled' => [ + [], [ 'mTOCEnabled' => false ], $text, <<<EOF +<p>Test document. +</p> + +<h2><span class="mw-headline" id="Section_1">Section 1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&action=edit&section=1" title="Edit section: Section 1">edit</a><span class="mw-editsection-bracket">]</span></span></h2> +<p>One +</p> +<h2><span class="mw-headline" id="Section_2">Section 2</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&action=edit&section=2" title="Edit section: Section 2">edit</a><span class="mw-editsection-bracket">]</span></span></h2> +<p>Two +</p> +<h3><span class="mw-headline" id="Section_2.1">Section 2.1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&action=edit&section=3" title="Edit section: Section 2.1">edit</a><span class="mw-editsection-bracket">]</span></span></h3> +<p>Two point one +</p> +<h2><span class="mw-headline" id="Section_3">Section 3</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&action=edit&section=4" title="Edit section: Section 3">edit</a><span class="mw-editsection-bracket">]</span></span></h2> +<p>Three +</p> +EOF + ], + 'No stateless options, section edits statefully disabled' => [ + [], [ 'mEditSectionTokens' => false ], $text, <<<EOF +<p>Test document. +</p> +<div id="toc" class="toc"><div class="toctitle"><h2>Contents</h2></div> +<ul> +<li class="toclevel-1 tocsection-1"><a href="#Section_1"><span class="tocnumber">1</span> <span class="toctext">Section 1</span></a></li> +<li class="toclevel-1 tocsection-2"><a href="#Section_2"><span class="tocnumber">2</span> <span class="toctext">Section 2</span></a> +<ul> +<li class="toclevel-2 tocsection-3"><a href="#Section_2.1"><span class="tocnumber">2.1</span> <span class="toctext">Section 2.1</span></a></li> +</ul> +</li> +<li class="toclevel-1 tocsection-4"><a href="#Section_3"><span class="tocnumber">3</span> <span class="toctext">Section 3</span></a></li> +</ul> +</div> + +<h2><span class="mw-headline" id="Section_1">Section 1</span></h2> +<p>One +</p> +<h2><span class="mw-headline" id="Section_2">Section 2</span></h2> +<p>Two +</p> +<h3><span class="mw-headline" id="Section_2.1">Section 2.1</span></h3> +<p>Two point one +</p> +<h2><span class="mw-headline" id="Section_3">Section 3</span></h2> +<p>Three +</p> +EOF + ], + 'Stateless options override stateful settings' => [ + [ 'allowTOC' => true, 'enableSectionEditLinks' => true ], + [ 'mTOCEnabled' => false, 'mEditSectionTokens' => false ], + $text, <<<EOF +<p>Test document. +</p> +<div id="toc" class="toc"><div class="toctitle"><h2>Contents</h2></div> +<ul> +<li class="toclevel-1 tocsection-1"><a href="#Section_1"><span class="tocnumber">1</span> <span class="toctext">Section 1</span></a></li> +<li class="toclevel-1 tocsection-2"><a href="#Section_2"><span class="tocnumber">2</span> <span class="toctext">Section 2</span></a> +<ul> +<li class="toclevel-2 tocsection-3"><a href="#Section_2.1"><span class="tocnumber">2.1</span> <span class="toctext">Section 2.1</span></a></li> +</ul> +</li> +<li class="toclevel-1 tocsection-4"><a href="#Section_3"><span class="tocnumber">3</span> <span class="toctext">Section 3</span></a></li> +</ul> +</div> + +<h2><span class="mw-headline" id="Section_1">Section 1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&action=edit&section=1" title="Edit section: Section 1">edit</a><span class="mw-editsection-bracket">]</span></span></h2> +<p>One +</p> +<h2><span class="mw-headline" id="Section_2">Section 2</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&action=edit&section=2" title="Edit section: Section 2">edit</a><span class="mw-editsection-bracket">]</span></span></h2> +<p>Two +</p> +<h3><span class="mw-headline" id="Section_2.1">Section 2.1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&action=edit&section=3" title="Edit section: Section 2.1">edit</a><span class="mw-editsection-bracket">]</span></span></h3> +<p>Two point one +</p> +<h2><span class="mw-headline" id="Section_3">Section 3</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&action=edit&section=4" title="Edit section: Section 3">edit</a><span class="mw-editsection-bracket">]</span></span></h2> +<p>Three +</p> +EOF + ], + 'Statelessly disable section edit links' => [ + [ 'enableSectionEditLinks' => false ], [], $text, <<<EOF +<p>Test document. +</p> +<div id="toc" class="toc"><div class="toctitle"><h2>Contents</h2></div> +<ul> +<li class="toclevel-1 tocsection-1"><a href="#Section_1"><span class="tocnumber">1</span> <span class="toctext">Section 1</span></a></li> +<li class="toclevel-1 tocsection-2"><a href="#Section_2"><span class="tocnumber">2</span> <span class="toctext">Section 2</span></a> +<ul> +<li class="toclevel-2 tocsection-3"><a href="#Section_2.1"><span class="tocnumber">2.1</span> <span class="toctext">Section 2.1</span></a></li> +</ul> +</li> +<li class="toclevel-1 tocsection-4"><a href="#Section_3"><span class="tocnumber">3</span> <span class="toctext">Section 3</span></a></li> +</ul> +</div> + +<h2><span class="mw-headline" id="Section_1">Section 1</span></h2> +<p>One +</p> +<h2><span class="mw-headline" id="Section_2">Section 2</span></h2> +<p>Two +</p> +<h3><span class="mw-headline" id="Section_2.1">Section 2.1</span></h3> +<p>Two point one +</p> +<h2><span class="mw-headline" id="Section_3">Section 3</span></h2> +<p>Three +</p> +EOF + ], + 'Statelessly disable TOC' => [ + [ 'allowTOC' => false ], [], $text, <<<EOF +<p>Test document. +</p> + +<h2><span class="mw-headline" id="Section_1">Section 1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&action=edit&section=1" title="Edit section: Section 1">edit</a><span class="mw-editsection-bracket">]</span></span></h2> +<p>One +</p> +<h2><span class="mw-headline" id="Section_2">Section 2</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&action=edit&section=2" title="Edit section: Section 2">edit</a><span class="mw-editsection-bracket">]</span></span></h2> +<p>Two +</p> +<h3><span class="mw-headline" id="Section_2.1">Section 2.1</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&action=edit&section=3" title="Edit section: Section 2.1">edit</a><span class="mw-editsection-bracket">]</span></span></h3> +<p>Two point one +</p> +<h2><span class="mw-headline" id="Section_3">Section 3</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Test_Page&action=edit&section=4" title="Edit section: Section 3">edit</a><span class="mw-editsection-bracket">]</span></span></h2> +<p>Three +</p> +EOF + ], + ]; + // @codingStandardsIgnoreEnd + } + } -- To view, visit https://gerrit.wikimedia.org/r/393260 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: Ied5fe1a6159c2d4fa48170042b44d735ce7b6f9b Gerrit-PatchSet: 4 Gerrit-Project: mediawiki/core Gerrit-Branch: master Gerrit-Owner: Anomie <bjor...@wikimedia.org> Gerrit-Reviewer: Anomie <bjor...@wikimedia.org> Gerrit-Reviewer: C. Scott Ananian <canan...@wikimedia.org> Gerrit-Reviewer: Jackmcbarn <jackmcb...@gmail.com> Gerrit-Reviewer: Krinkle <krinklem...@gmail.com> Gerrit-Reviewer: Legoktm <lego...@member.fsf.org> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits