From: Brad Jorsch
Date: Wed, 22 Nov 2017 18:12:23 +0000 (-0500)
Subject: ParserOutput: Add stateless transforms to getText()
X-Git-Tag: 1.31.0-rc.0~734^2~2
X-Git-Url: https://git.cyclocoop.org/%7B%24admin_url%7Dmembres/Main?a=commitdiff_plain;h=92cf49df5ca0c5dea25f5ae651996d79a2ce25af;p=lhc%2Fweb%2Fwiklou.git
ParserOutput: Add stateless transforms to getText()
The stateful transforms are deprecated.
Inspired by Krinkle's If2fb32fc.
Bug: T171797
Change-Id: Ied5fe1a6159c2d4fa48170042b44d735ce7b6f9b
---
diff --git a/RELEASE-NOTES-1.31 b/RELEASE-NOTES-1.31
index b32e3e755e..139773b573 100644
--- a/RELEASE-NOTES-1.31
+++ b/RELEASE-NOTES-1.31
@@ -31,6 +31,8 @@ production.
[[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 @@ changes to languages because of Phabricator reports.
* 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 685a182a55..29883b25a6 100644
--- a/docs/hooks.txt
+++ b/docs/hooks.txt
@@ -2594,6 +2594,12 @@ RejectParserCacheValue hook) because MediaWiki won't do it for you.
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 5e2845ffe2..f99089b895 100644
--- a/includes/parser/ParserOptions.php
+++ b/includes/parser/ParserOptions.php
@@ -869,6 +869,7 @@ class ParserOptions {
/**
* Create "edit section" links?
+ * @deprecated since 1.31, use ParserOutput::getText() options instead.
* @return bool
*/
public function getEditSection() {
@@ -877,6 +878,7 @@ class ParserOptions {
/**
* 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 3480a51f3c..59c27e5db1 100644
--- a/includes/parser/ParserOutput.php
+++ b/includes/parser/ParserOutput.php
@@ -144,6 +144,7 @@ class ParserOutput extends CacheTime {
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 @@ class ParserOutput extends CacheTime {
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 @@ class ParserOutput extends CacheTime {
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 @@ class ParserOutput extends CacheTime {
$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 @@ class ParserOutput extends CacheTime {
$text
);
}
+
return $text;
}
@@ -339,6 +370,9 @@ class ParserOutput extends CacheTime {
return $this->mSections;
}
+ /**
+ * @deprecated since 1.31 Use getText() options.
+ */
public function getEditSectionTokens() {
return $this->mEditSectionTokens;
}
@@ -426,6 +460,9 @@ class ParserOutput extends CacheTime {
return $this->mLimitReportJSData;
}
+ /**
+ * @deprecated since 1.31 Use getText() options.
+ */
public function getTOCEnabled() {
return $this->mTOCEnabled;
}
@@ -454,6 +491,9 @@ class ParserOutput extends CacheTime {
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 @@ class ParserOutput extends CacheTime {
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 ec8f0d076d..441d60df7b 100644
--- a/tests/phpunit/includes/parser/ParserOutputTest.php
+++ b/tests/phpunit/includes/parser/ParserOutputTest.php
@@ -1,5 +1,7 @@
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 = <<Test document.
+
+
+
+Section 1Section 1
+One
+
+Section 2Section 2
+Two
+
+Section 2.1Section 2.1
+Two point one
+
+Section 3Section 3
+Three
+
+EOF;
+
+ return [
+ 'No stateless options, default state' => [
+ [], [], $text, <<Test document.
+
+
+
+Section 1[edit]
+One
+
+Section 2[edit]
+Two
+
+Section 2.1[edit]
+Two point one
+
+Section 3[edit]
+Three
+
+EOF
+ ],
+ 'No stateless options, TOC statefully disabled' => [
+ [], [ 'mTOCEnabled' => false ], $text, <<Test document.
+
+
+Section 1[edit]
+One
+
+Section 2[edit]
+Two
+
+Section 2.1[edit]
+Two point one
+
+Section 3[edit]
+Three
+
+EOF
+ ],
+ 'No stateless options, section edits statefully disabled' => [
+ [], [ 'mEditSectionTokens' => false ], $text, <<Test document.
+
+
+
+Section 1
+One
+
+Section 2
+Two
+
+Section 2.1
+Two point one
+
+Section 3
+Three
+
+EOF
+ ],
+ 'Stateless options override stateful settings' => [
+ [ 'allowTOC' => true, 'enableSectionEditLinks' => true ],
+ [ 'mTOCEnabled' => false, 'mEditSectionTokens' => false ],
+ $text, <<Test document.
+
+
+
+Section 1[edit]
+One
+
+Section 2[edit]
+Two
+
+Section 2.1[edit]
+Two point one
+
+Section 3[edit]
+Three
+
+EOF
+ ],
+ 'Statelessly disable section edit links' => [
+ [ 'enableSectionEditLinks' => false ], [], $text, <<Test document.
+
+
+
+Section 1
+One
+
+Section 2
+Two
+
+Section 2.1
+Two point one
+
+Section 3
+Three
+
+EOF
+ ],
+ 'Statelessly disable TOC' => [
+ [ 'allowTOC' => false ], [], $text, <<Test document.
+
+
+Section 1[edit]
+One
+
+Section 2[edit]
+Two
+
+Section 2.1[edit]
+Two point one
+
+Section 3[edit]
+Three
+
+EOF
+ ],
+ ];
+ // @codingStandardsIgnoreEnd
+ }
+
}