Index: trunk/phase3/includes/parser/Parser.php |
— | — | @@ -3696,6 +3696,12 @@ |
3697 | 3697 | } else { |
3698 | 3698 | $showEditLink = $this->mOptions->getEditSection(); |
3699 | 3699 | } |
| 3700 | + if ( $showEditLink ) { |
| 3701 | + $editLinkAsToken = $this->mOptions->getEditSectionTokens(); |
| 3702 | + if ( $editLinkAsToken ) { |
| 3703 | + $this->mOutput->setEditSectionTokens( "{$this->mUniqPrefix}-editsection-", self::MARKER_SUFFIX ); |
| 3704 | + } |
| 3705 | + } |
3700 | 3706 | |
3701 | 3707 | # Get all headlines for numbering them and adding funky stuff like [edit] |
3702 | 3708 | # links - this is for later, but we need the number of headlines right now |
— | — | @@ -3949,12 +3955,28 @@ |
3950 | 3956 | |
3951 | 3957 | # give headline the correct <h#> tag |
3952 | 3958 | if ( $showEditLink && $sectionIndex !== false ) { |
3953 | | - if ( $isTemplate ) { |
3954 | | - # Put a T flag in the section identifier, to indicate to extractSections() |
3955 | | - # that sections inside <includeonly> should be counted. |
3956 | | - $editlink = $sk->doEditSectionLink( Title::newFromText( $titleText ), "T-$sectionIndex", null, $this->mOptions->getUserLang() ); |
| 3959 | + if ( $editLinkAsToken ) { |
| 3960 | + // Output edit section links as markers with styles that can be customized by skins |
| 3961 | + if ( $isTemplate ) { |
| 3962 | + # Put a T flag in the section identifier, to indicate to extractSections() |
| 3963 | + # that sections inside <includeonly> should be counted. |
| 3964 | + $editlinkArgs = array( $titleText, "T-$sectionIndex", null ); |
| 3965 | + } else { |
| 3966 | + $editlinkArgs = array( $this->mTitle->getPrefixedText(), $sectionIndex, $headlineHint ); |
| 3967 | + } |
| 3968 | + // We use nearly the same structure as uniqPrefix and the marker stuffix (besides there being nothing random) |
| 3969 | + // However the this is output into the parser output itself not replaced early, so we hardcode this in case |
| 3970 | + // the constants change in a different version of MediaWiki, which would break this code. |
| 3971 | + $editlink = "{$this->mUniqPrefix}-editsection-" . serialize($editlinkArgs) . self::MARKER_SUFFIX; |
3957 | 3972 | } else { |
3958 | | - $editlink = $sk->doEditSectionLink( $this->mTitle, $sectionIndex, $headlineHint, $this->mOptions->getUserLang() ); |
| 3973 | + // Output edit section links directly as markup like we used to |
| 3974 | + if ( $isTemplate ) { |
| 3975 | + # Put a T flag in the section identifier, to indicate to extractSections() |
| 3976 | + # that sections inside <includeonly> should be counted. |
| 3977 | + $editlink = $sk->doEditSectionLink( Title::newFromText( $titleText ), "T-$sectionIndex", null, $this->mOptions->getUserLang() ); |
| 3978 | + } else { |
| 3979 | + $editlink = $sk->doEditSectionLink( $this->mTitle, $sectionIndex, $headlineHint, $this->mOptions->getUserLang() ); |
| 3980 | + } |
3959 | 3981 | } |
3960 | 3982 | } else { |
3961 | 3983 | $editlink = ''; |
Index: trunk/phase3/includes/parser/ParserOutput.php |
— | — | @@ -119,6 +119,7 @@ |
120 | 120 | $mOutputHooks = array(), # Hook tags as per $wgParserOutputHooks |
121 | 121 | $mWarnings = array(), # Warning text to be returned to the user. Wikitext formatted, in the key only |
122 | 122 | $mSections = array(), # Table of contents |
| 123 | + $mEditSectionTokens = false, # prefix/suffix markers if edit sections were output as tokens |
123 | 124 | $mProperties = array(), # Name/value pairs to be cached in the DB |
124 | 125 | $mTOCHTML = ''; # HTML of the TOC |
125 | 126 | private $mIndexPolicy = ''; # 'index' or 'noindex'? Any other value will result in no change. |
— | — | @@ -134,13 +135,34 @@ |
135 | 136 | $this->mTitleText = $titletext; |
136 | 137 | } |
137 | 138 | |
138 | | - function getText() { return $this->mText; } |
| 139 | + function getText() { |
| 140 | + if ( $this->mEditSectionTokens ) { |
| 141 | + $editSectionTokens = $this->mEditSectionTokens; |
| 142 | + return preg_replace_callback( "#{$editSectionTokens[0]}(.*?){$editSectionTokens[1]}#", array( &$this, 'replaceEditSectionLinksCallback' ), $this->mText ); |
| 143 | + } |
| 144 | + return $this->mText; |
| 145 | + } |
| 146 | + |
| 147 | + /** |
| 148 | + * callback used by getText to replace editsection tokens |
| 149 | + * @private |
| 150 | + */ |
| 151 | + function replaceEditSectionLinksCallback( $m ) { |
| 152 | + global $wgUser, $wgLang; |
| 153 | + $args = unserialize($m[1]); |
| 154 | + $args[0] = Title::newFromText( $args[0] ); |
| 155 | + $args[] = $wgLang->getCode(); |
| 156 | + $skin = $wgUser->getSkin(); |
| 157 | + return call_user_func_array( array( $skin, 'doEditSectionLink' ), $args ); |
| 158 | + } |
| 159 | + |
139 | 160 | function &getLanguageLinks() { return $this->mLanguageLinks; } |
140 | 161 | function getInterwikiLinks() { return $this->mInterwikiLinks; } |
141 | 162 | function getCategoryLinks() { return array_keys( $this->mCategories ); } |
142 | 163 | function &getCategories() { return $this->mCategories; } |
143 | 164 | function getTitleText() { return $this->mTitleText; } |
144 | 165 | function getSections() { return $this->mSections; } |
| 166 | + function getEditSectionTokens() { return $this->mEditSectionTokens; } |
145 | 167 | function &getLinks() { return $this->mLinks; } |
146 | 168 | function &getTemplates() { return $this->mTemplates; } |
147 | 169 | function &getImages() { return $this->mImages; } |
— | — | @@ -159,6 +181,7 @@ |
160 | 182 | |
161 | 183 | function setTitleText( $t ) { return wfSetVar( $this->mTitleText, $t ); } |
162 | 184 | function setSections( $toc ) { return wfSetVar( $this->mSections, $toc ); } |
| 185 | + function setEditSectionTokens( $p, $s ) { return wfSetVar( $this->mEditSectionTokens, array( $p, $s ) ); } |
163 | 186 | function setIndexPolicy( $policy ) { return wfSetVar( $this->mIndexPolicy, $policy ); } |
164 | 187 | function setTOCHTML( $tochtml ) { return wfSetVar( $this->mTOCHTML, $tochtml ); } |
165 | 188 | |
Index: trunk/phase3/includes/parser/ParserOptions.php |
— | — | @@ -21,6 +21,7 @@ |
22 | 22 | var $mSkin = null; # Reference to the preferred skin |
23 | 23 | var $mDateFormat = null; # Date format index |
24 | 24 | var $mEditSection = true; # Create "edit section" links |
| 25 | + var $mEditSectionTokens = false; # Output replaceable tokens for editsections instead of markup |
25 | 26 | var $mAllowSpecialInclusion; # Allow inclusion of special pages |
26 | 27 | var $mTidy = false; # Ask for tidy cleanup |
27 | 28 | var $mInterfaceMessage = false; # Which lang to call for PLURAL and GRAMMAR |
— | — | @@ -58,6 +59,8 @@ |
59 | 60 | function getEnableImageWhitelist() { return $this->mEnableImageWhitelist; } |
60 | 61 | function getEditSection() { $this->optionUsed('editsection'); |
61 | 62 | return $this->mEditSection; } |
| 63 | + function getEditSectionTokens() { $this->optionUsed('editsectiontokens'); |
| 64 | + return $this->mEditSectionTokens; } |
62 | 65 | function getNumberHeadings() { $this->optionUsed('numberheadings'); |
63 | 66 | return $this->mNumberHeadings; } |
64 | 67 | function getAllowSpecialInclusion() { return $this->mAllowSpecialInclusion; } |
— | — | @@ -123,6 +126,7 @@ |
124 | 127 | function setEnableImageWhitelist( $x ) { return wfSetVar( $this->mEnableImageWhitelist, $x ); } |
125 | 128 | function setDateFormat( $x ) { return wfSetVar( $this->mDateFormat, $x ); } |
126 | 129 | function setEditSection( $x ) { return wfSetVar( $this->mEditSection, $x ); } |
| 130 | + function setEditSectionTokens( $x ) { return wfSetVar( $this->mEditSectionTokens, $x ); } |
127 | 131 | function setNumberHeadings( $x ) { return wfSetVar( $this->mNumberHeadings, $x ); } |
128 | 132 | function setAllowSpecialInclusion( $x ) { return wfSetVar( $this->mAllowSpecialInclusion, $x ); } |
129 | 133 | function setTidy( $x ) { return wfSetVar( $this->mTidy, $x); } |
— | — | @@ -171,7 +175,7 @@ |
172 | 176 | function initialiseFromUser( $userInput ) { |
173 | 177 | global $wgUseDynamicDates, $wgInterwikiMagic, $wgAllowExternalImages; |
174 | 178 | global $wgAllowExternalImagesFrom, $wgEnableImageWhitelist, $wgAllowSpecialInclusion, $wgMaxArticleSize; |
175 | | - global $wgMaxPPNodeCount, $wgMaxTemplateDepth, $wgMaxPPExpandDepth, $wgCleanSignatures; |
| 179 | + global $wgMaxPPNodeCount, $wgMaxTemplateDepth, $wgMaxPPExpandDepth, $wgCleanSignatures, $wgUseEditSectionTokens; |
176 | 180 | global $wgExternalLinkTarget, $wgLang; |
177 | 181 | |
178 | 182 | wfProfileIn( __METHOD__ ); |
— | — | @@ -201,6 +205,7 @@ |
202 | 206 | $this->mMaxTemplateDepth = $wgMaxTemplateDepth; |
203 | 207 | $this->mCleanSignatures = $wgCleanSignatures; |
204 | 208 | $this->mExternalLinkTarget = $wgExternalLinkTarget; |
| 209 | + $this->mEditSectionTokens = $wgUseEditSectionTokens; |
205 | 210 | |
206 | 211 | $this->mNumberHeadings = $user->getOption( 'numberheadings' ); |
207 | 212 | $this->mMath = $user->getOption( 'math' ); |
— | — | @@ -307,6 +312,8 @@ |
308 | 313 | |
309 | 314 | if ( !$this->mEditSection && in_array( 'editsection', $forOptions ) ) |
310 | 315 | $confstr .= '!edit=0'; |
| 316 | + if ( $this->mEditSectionTokens && in_array( 'editsectiontokens', $forOptions ) ) |
| 317 | + $confstr .= '!estok=1'; |
311 | 318 | if ( $this->mIsPrintable && in_array( 'printable', $forOptions ) ) |
312 | 319 | $confstr .= '!printable=1'; |
313 | 320 | |
Index: trunk/phase3/includes/DefaultSettings.php |
— | — | @@ -2825,6 +2825,18 @@ |
2826 | 2826 | */ |
2827 | 2827 | $wgTranscludeCacheExpiry = 3600; |
2828 | 2828 | |
| 2829 | +/** |
| 2830 | + * Output edit section links as tokens in the parser output for articles instead |
| 2831 | + * of directly as markup. |
| 2832 | + * This feature changes the default parser cache key so it's presented with a |
| 2833 | + * configuration option so that large installations with a large number of already |
| 2834 | + * existing parser cache keys can retain them. |
| 2835 | + * The purpose of this feature is to allow skins to customize the editsection |
| 2836 | + * links, however it has the side effect of also removing the most common use of |
| 2837 | + * the getUserLang parser option which causes cache fragmentation by user lang. |
| 2838 | + */ |
| 2839 | +$wgUseEditSectionTokens = true; |
| 2840 | + |
2829 | 2841 | /** @} */ # end of parser settings } |
2830 | 2842 | |
2831 | 2843 | /************************************************************************//** |
Index: trunk/phase3/RELEASE-NOTES |
— | — | @@ -26,6 +26,11 @@ |
27 | 27 | * Skin names are no longer created based on a ucfirst version of the key in $wgValidSkinNames but now |
28 | 28 | the value. This means for $wgValidSkinNames["monobook"] = "MonoBook"; the skin |
29 | 29 | loader will no longer try loading SkinMonobook and will instead load SkinMonoBook. |
| 30 | +* The parser now attempts to output markers for editsection tokens and defer the rendering |
| 31 | + of them so skin and language specific markup does not need to be saved inside the parser cache |
| 32 | + note that this changes the cache key making all old entries in the parser cache invalid you |
| 33 | + can set $wgUseEditSectionTokens to false to disable this and keep your old parser cache entries. |
| 34 | + Note that this feature should reduce parser cache fragmentation when enabled. |
30 | 35 | |
31 | 36 | === New features in 1.18 === |
32 | 37 | * Added a special page, disabled by default, that allows users with the |