Try to output editsection markers instead of rendered editsection links and defer the rendering to a point where the markup does not need to be stored in the cache.
Doing this allows skins to override doEditSectionLinks without poluting the parser cache or fragmenting the parser cache more. As a side effect it eliminates the primary cause of user language based parser cache fragmentation. Because this makes most old parser cache entries invalid $wgUseEditSectionTokens is provided so that large installations like Wikipedia can keep their old parser cache entries.
This commit is contained in:
parent
49aa485313
commit
969561ae3c
5 changed files with 76 additions and 7 deletions
|
|
@ -26,6 +26,11 @@ it from source control: http://www.mediawiki.org/wiki/Download_from_SVN
|
|||
* Skin names are no longer created based on a ucfirst version of the key in $wgValidSkinNames but now
|
||||
the value. This means for $wgValidSkinNames["monobook"] = "MonoBook"; the skin
|
||||
loader will no longer try loading SkinMonobook and will instead load SkinMonoBook.
|
||||
* The parser now attempts to output markers for editsection tokens and defer the rendering
|
||||
of them so skin and language specific markup does not need to be saved inside the parser cache
|
||||
note that this changes the cache key making all old entries in the parser cache invalid you
|
||||
can set $wgUseEditSectionTokens to false to disable this and keep your old parser cache entries.
|
||||
Note that this feature should reduce parser cache fragmentation when enabled.
|
||||
|
||||
=== New features in 1.18 ===
|
||||
* Added a special page, disabled by default, that allows users with the
|
||||
|
|
|
|||
|
|
@ -2825,6 +2825,18 @@ $wgEnableScaryTranscluding = false;
|
|||
*/
|
||||
$wgTranscludeCacheExpiry = 3600;
|
||||
|
||||
/**
|
||||
* Output edit section links as tokens in the parser output for articles instead
|
||||
* of directly as markup.
|
||||
* This feature changes the default parser cache key so it's presented with a
|
||||
* configuration option so that large installations with a large number of already
|
||||
* existing parser cache keys can retain them.
|
||||
* The purpose of this feature is to allow skins to customize the editsection
|
||||
* links, however it has the side effect of also removing the most common use of
|
||||
* the getUserLang parser option which causes cache fragmentation by user lang.
|
||||
*/
|
||||
$wgUseEditSectionTokens = true;
|
||||
|
||||
/** @} */ # end of parser settings }
|
||||
|
||||
/************************************************************************//**
|
||||
|
|
|
|||
|
|
@ -3696,6 +3696,12 @@ class Parser {
|
|||
} else {
|
||||
$showEditLink = $this->mOptions->getEditSection();
|
||||
}
|
||||
if ( $showEditLink ) {
|
||||
$editLinkAsToken = $this->mOptions->getEditSectionTokens();
|
||||
if ( $editLinkAsToken ) {
|
||||
$this->mOutput->setEditSectionTokens( "{$this->mUniqPrefix}-editsection-", self::MARKER_SUFFIX );
|
||||
}
|
||||
}
|
||||
|
||||
# Get all headlines for numbering them and adding funky stuff like [edit]
|
||||
# links - this is for later, but we need the number of headlines right now
|
||||
|
|
@ -3949,12 +3955,28 @@ class Parser {
|
|||
|
||||
# give headline the correct <h#> tag
|
||||
if ( $showEditLink && $sectionIndex !== false ) {
|
||||
if ( $isTemplate ) {
|
||||
# Put a T flag in the section identifier, to indicate to extractSections()
|
||||
# that sections inside <includeonly> should be counted.
|
||||
$editlink = $sk->doEditSectionLink( Title::newFromText( $titleText ), "T-$sectionIndex", null, $this->mOptions->getUserLang() );
|
||||
if ( $editLinkAsToken ) {
|
||||
// Output edit section links as markers with styles that can be customized by skins
|
||||
if ( $isTemplate ) {
|
||||
# Put a T flag in the section identifier, to indicate to extractSections()
|
||||
# that sections inside <includeonly> should be counted.
|
||||
$editlinkArgs = array( $titleText, "T-$sectionIndex", null );
|
||||
} else {
|
||||
$editlinkArgs = array( $this->mTitle->getPrefixedText(), $sectionIndex, $headlineHint );
|
||||
}
|
||||
// We use nearly the same structure as uniqPrefix and the marker stuffix (besides there being nothing random)
|
||||
// However the this is output into the parser output itself not replaced early, so we hardcode this in case
|
||||
// the constants change in a different version of MediaWiki, which would break this code.
|
||||
$editlink = "{$this->mUniqPrefix}-editsection-" . serialize($editlinkArgs) . self::MARKER_SUFFIX;
|
||||
} else {
|
||||
$editlink = $sk->doEditSectionLink( $this->mTitle, $sectionIndex, $headlineHint, $this->mOptions->getUserLang() );
|
||||
// Output edit section links directly as markup like we used to
|
||||
if ( $isTemplate ) {
|
||||
# Put a T flag in the section identifier, to indicate to extractSections()
|
||||
# that sections inside <includeonly> should be counted.
|
||||
$editlink = $sk->doEditSectionLink( Title::newFromText( $titleText ), "T-$sectionIndex", null, $this->mOptions->getUserLang() );
|
||||
} else {
|
||||
$editlink = $sk->doEditSectionLink( $this->mTitle, $sectionIndex, $headlineHint, $this->mOptions->getUserLang() );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$editlink = '';
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ class ParserOptions {
|
|||
var $mSkin = null; # Reference to the preferred skin
|
||||
var $mDateFormat = null; # Date format index
|
||||
var $mEditSection = true; # Create "edit section" links
|
||||
var $mEditSectionTokens = false; # Output replaceable tokens for editsections instead of markup
|
||||
var $mAllowSpecialInclusion; # Allow inclusion of special pages
|
||||
var $mTidy = false; # Ask for tidy cleanup
|
||||
var $mInterfaceMessage = false; # Which lang to call for PLURAL and GRAMMAR
|
||||
|
|
@ -58,6 +59,8 @@ class ParserOptions {
|
|||
function getEnableImageWhitelist() { return $this->mEnableImageWhitelist; }
|
||||
function getEditSection() { $this->optionUsed('editsection');
|
||||
return $this->mEditSection; }
|
||||
function getEditSectionTokens() { $this->optionUsed('editsectiontokens');
|
||||
return $this->mEditSectionTokens; }
|
||||
function getNumberHeadings() { $this->optionUsed('numberheadings');
|
||||
return $this->mNumberHeadings; }
|
||||
function getAllowSpecialInclusion() { return $this->mAllowSpecialInclusion; }
|
||||
|
|
@ -123,6 +126,7 @@ class ParserOptions {
|
|||
function setEnableImageWhitelist( $x ) { return wfSetVar( $this->mEnableImageWhitelist, $x ); }
|
||||
function setDateFormat( $x ) { return wfSetVar( $this->mDateFormat, $x ); }
|
||||
function setEditSection( $x ) { return wfSetVar( $this->mEditSection, $x ); }
|
||||
function setEditSectionTokens( $x ) { return wfSetVar( $this->mEditSectionTokens, $x ); }
|
||||
function setNumberHeadings( $x ) { return wfSetVar( $this->mNumberHeadings, $x ); }
|
||||
function setAllowSpecialInclusion( $x ) { return wfSetVar( $this->mAllowSpecialInclusion, $x ); }
|
||||
function setTidy( $x ) { return wfSetVar( $this->mTidy, $x); }
|
||||
|
|
@ -171,7 +175,7 @@ class ParserOptions {
|
|||
function initialiseFromUser( $userInput ) {
|
||||
global $wgUseDynamicDates, $wgInterwikiMagic, $wgAllowExternalImages;
|
||||
global $wgAllowExternalImagesFrom, $wgEnableImageWhitelist, $wgAllowSpecialInclusion, $wgMaxArticleSize;
|
||||
global $wgMaxPPNodeCount, $wgMaxTemplateDepth, $wgMaxPPExpandDepth, $wgCleanSignatures;
|
||||
global $wgMaxPPNodeCount, $wgMaxTemplateDepth, $wgMaxPPExpandDepth, $wgCleanSignatures, $wgUseEditSectionTokens;
|
||||
global $wgExternalLinkTarget, $wgLang;
|
||||
|
||||
wfProfileIn( __METHOD__ );
|
||||
|
|
@ -201,6 +205,7 @@ class ParserOptions {
|
|||
$this->mMaxTemplateDepth = $wgMaxTemplateDepth;
|
||||
$this->mCleanSignatures = $wgCleanSignatures;
|
||||
$this->mExternalLinkTarget = $wgExternalLinkTarget;
|
||||
$this->mEditSectionTokens = $wgUseEditSectionTokens;
|
||||
|
||||
$this->mNumberHeadings = $user->getOption( 'numberheadings' );
|
||||
$this->mMath = $user->getOption( 'math' );
|
||||
|
|
@ -307,6 +312,8 @@ class ParserOptions {
|
|||
|
||||
if ( !$this->mEditSection && in_array( 'editsection', $forOptions ) )
|
||||
$confstr .= '!edit=0';
|
||||
if ( $this->mEditSectionTokens && in_array( 'editsectiontokens', $forOptions ) )
|
||||
$confstr .= '!estok=1';
|
||||
if ( $this->mIsPrintable && in_array( 'printable', $forOptions ) )
|
||||
$confstr .= '!printable=1';
|
||||
|
||||
|
|
|
|||
|
|
@ -119,6 +119,7 @@ class ParserOutput extends CacheTime {
|
|||
$mOutputHooks = array(), # Hook tags as per $wgParserOutputHooks
|
||||
$mWarnings = array(), # Warning text to be returned to the user. Wikitext formatted, in the key only
|
||||
$mSections = array(), # Table of contents
|
||||
$mEditSectionTokens = false, # prefix/suffix markers if edit sections were output as tokens
|
||||
$mProperties = array(), # Name/value pairs to be cached in the DB
|
||||
$mTOCHTML = ''; # HTML of the TOC
|
||||
private $mIndexPolicy = ''; # 'index' or 'noindex'? Any other value will result in no change.
|
||||
|
|
@ -134,13 +135,34 @@ class ParserOutput extends CacheTime {
|
|||
$this->mTitleText = $titletext;
|
||||
}
|
||||
|
||||
function getText() { return $this->mText; }
|
||||
function getText() {
|
||||
if ( $this->mEditSectionTokens ) {
|
||||
$editSectionTokens = $this->mEditSectionTokens;
|
||||
return preg_replace_callback( "#{$editSectionTokens[0]}(.*?){$editSectionTokens[1]}#", array( &$this, 'replaceEditSectionLinksCallback' ), $this->mText );
|
||||
}
|
||||
return $this->mText;
|
||||
}
|
||||
|
||||
/**
|
||||
* callback used by getText to replace editsection tokens
|
||||
* @private
|
||||
*/
|
||||
function replaceEditSectionLinksCallback( $m ) {
|
||||
global $wgUser, $wgLang;
|
||||
$args = unserialize($m[1]);
|
||||
$args[0] = Title::newFromText( $args[0] );
|
||||
$args[] = $wgLang->getCode();
|
||||
$skin = $wgUser->getSkin();
|
||||
return call_user_func_array( array( $skin, 'doEditSectionLink' ), $args );
|
||||
}
|
||||
|
||||
function &getLanguageLinks() { return $this->mLanguageLinks; }
|
||||
function getInterwikiLinks() { return $this->mInterwikiLinks; }
|
||||
function getCategoryLinks() { return array_keys( $this->mCategories ); }
|
||||
function &getCategories() { return $this->mCategories; }
|
||||
function getTitleText() { return $this->mTitleText; }
|
||||
function getSections() { return $this->mSections; }
|
||||
function getEditSectionTokens() { return $this->mEditSectionTokens; }
|
||||
function &getLinks() { return $this->mLinks; }
|
||||
function &getTemplates() { return $this->mTemplates; }
|
||||
function &getImages() { return $this->mImages; }
|
||||
|
|
@ -159,6 +181,7 @@ class ParserOutput extends CacheTime {
|
|||
|
||||
function setTitleText( $t ) { return wfSetVar( $this->mTitleText, $t ); }
|
||||
function setSections( $toc ) { return wfSetVar( $this->mSections, $toc ); }
|
||||
function setEditSectionTokens( $p, $s ) { return wfSetVar( $this->mEditSectionTokens, array( $p, $s ) ); }
|
||||
function setIndexPolicy( $policy ) { return wfSetVar( $this->mIndexPolicy, $policy ); }
|
||||
function setTOCHTML( $tochtml ) { return wfSetVar( $this->mTOCHTML, $tochtml ); }
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue