*/
private static $inCacheKey = [
'dateformat' => true,
- 'editsection' => true,
'numberheadings' => true,
'thumbsize' => true,
'stubthreshold' => true,
*/
private $mTimestamp;
+ /**
+ * The edit section flag is in ParserOptions for historical reasons, but
+ * doesn't actually affect the parser output since Feb 2015.
+ * @var bool
+ */
+ private $mEditSection = true;
+
/**
* Stored user object
* @var User
return $this->setOptionLegacy( 'enableImageWhitelist', $x );
}
- /**
- * Create "edit section" links?
- * @return bool
- */
- public function getEditSection() {
- return $this->getOption( 'editsection' );
- }
-
- /**
- * Create "edit section" links?
- * @param bool|null $x New value (null is no change)
- * @return bool Old value
- */
- public function setEditSection( $x ) {
- return $this->setOptionLegacy( 'editsection', $x );
- }
-
/**
* Automatically number headings?
* @return bool
return wfSetVar( $this->mTimestamp, $x );
}
+ /**
+ * Create "edit section" links?
+ * @return bool
+ */
+ public function getEditSection() {
+ return $this->mEditSection;
+ }
+
+ /**
+ * Create "edit section" links?
+ * @param bool|null $x New value (null is no change)
+ * @return bool Old value
+ */
+ public function setEditSection( $x ) {
+ return wfSetVar( $this->mEditSection, $x );
+ }
+
/**
* Set the redirect target.
*
// *UPDATE* ParserOptions::matches() if any of this changes as needed
self::$defaults = [
'dateformat' => null,
- 'editsection' => true,
'tidy' => false,
'interfaceMessage' => false,
'targetLanguage' => null,
public function optionsHash( $forOptions, $title = null ) {
global $wgRenderHashAppend;
+ $options = $this->options;
+ $defaults = self::getCanonicalOverrides() + self::getDefaults();
+ $inCacheKey = self::$inCacheKey;
+
+ // Historical hack: 'editsection' hasn't been a true parser option since
+ // Feb 2015 (instead the parser outputs a constant placeholder and post-parse
+ // processing handles the option). But Wikibase forces it in $forOptions
+ // and expects the cache key to still vary on it for T85252.
+ // @todo Deprecate and remove this behavior after optionsHashPre30() is
+ // removed (Wikibase can use addExtraKey() or something instead).
+ if ( in_array( 'editsection', $forOptions, true ) ) {
+ $options['editsection'] = $this->mEditSection;
+ $defaults['editsection'] = true;
+ $inCacheKey['editsection'] = true;
+ ksort( $inCacheKey );
+ }
+
// We only include used options with non-canonical values in the key
// so adding a new option doesn't invalidate the entire parser cache.
// The drawback to this is that changing the default value of an option
// requires manual invalidation of existing cache entries, as mentioned
// in the docs on the relevant methods and hooks.
- $defaults = self::getCanonicalOverrides() + self::getDefaults();
$values = [];
- foreach ( self::$inCacheKey as $option => $include ) {
+ foreach ( $inCacheKey as $option => $include ) {
if ( $include && in_array( $option, $forOptions, true ) ) {
- $v = $this->optionToString( $this->options[$option] );
+ $v = $this->optionToString( $options[$option] );
$d = $this->optionToString( $defaults[$option] );
if ( $v !== $d ) {
$values[] = "$option=$v";
// directly. At least Wikibase does at this point in time.
if ( !in_array( 'editsection', $forOptions ) ) {
$confstr .= '!*';
- } elseif ( !$this->options['editsection'] ) {
+ } elseif ( !$this->mEditSection ) {
$confstr .= '!edit=0';
}
return [
'No overrides' => [ true, [] ],
'In-key options are ok' => [ true, [
- 'editsection' => false,
'thumbsize' => 1e100,
'wrapclass' => false,
] ],
}
public static function provideOptionsHashPre30() {
- $used = [ 'wrapclass', 'editsection', 'printable' ];
+ $used = [ 'wrapclass', 'printable' ];
return [
'Canonical options, nothing used' => [ [], '*!*!*!*!*!*', [] ],
- 'Canonical options, used some options' => [ $used, '*!*!*!*!*', [] ],
+ 'Canonical options, used some options' => [ $used, '*!*!*!*!*!*', [] ],
'Used some options, non-default values' => [
$used,
- '*!*!*!*!*!printable=1!wrapclass=foobar',
+ '*!*!*!*!*!*!printable=1!wrapclass=foobar',
[
'setWrapOutputClass' => 'foobar',
'setIsPrintable' => true,
'wgHooks' => [ 'PageRenderingHash' => [ [ __CLASS__ . '::onPageRenderingHash' ] ] ],
]
],
+
+ // Test weird historical behavior is still weird
+ 'Canonical options, editsection=true used' => [ [ 'editsection' ], '*!*!*!*!*', [
+ 'setEditSection' => true,
+ ] ],
+ 'Canonical options, editsection=false used' => [ [ 'editsection' ], '*!*!*!*!*!edit=0', [
+ 'setEditSection' => false,
+ ] ],
];
}
}
public static function provideOptionsHash() {
- $used = [ 'wrapclass', 'editsection', 'printable' ];
+ $used = [ 'wrapclass', 'printable' ];
$classWrapper = TestingAccessWrapper::newFromClass( ParserOptions::class );
$classWrapper->getDefaults();
$confstr .= '!onPageRenderingHash';
}
+ // Test weird historical behavior is still weird
+ public function testOptionsHashEditSection() {
+ global $wgHooks;
+
+ $this->setMwGlobals( [
+ 'wgRenderHashAppend' => '',
+ 'wgHooks' => [ 'PageRenderingHash' => [] ] + $wgHooks,
+ ] );
+
+ $popt = ParserOptions::newCanonical();
+ $popt->registerWatcher( function ( $name ) {
+ $this->assertNotEquals( 'editsection', $name );
+ } );
+
+ $this->assertTrue( $popt->getEditSection() );
+ $this->assertSame( 'canonical', $popt->optionsHash( [] ) );
+ $this->assertSame( 'canonical', $popt->optionsHash( [ 'editsection' ] ) );
+
+ $popt->setEditSection( false );
+ $this->assertFalse( $popt->getEditSection() );
+ $this->assertSame( 'canonical', $popt->optionsHash( [] ) );
+ $this->assertSame( 'editsection=0', $popt->optionsHash( [ 'editsection' ] ) );
+ }
+
/**
* @expectedException InvalidArgumentException
* @expectedExceptionMessage Unknown parser option bogus