3 * Options for the PHP parser
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * http://www.gnu.org/copyleft/gpl.html
25 * \brief Set options of the Parser
27 * All member variables are supposed to be private in theory, although in
28 * practise this is not the case.
35 * Interlanguage links are removed and returned in an array
40 * Allow external images inline?
42 var $mAllowExternalImages;
45 * If not, any exception?
47 var $mAllowExternalImagesFrom;
50 * If not or it doesn't match, should we check an on-wiki whitelist?
52 var $mEnableImageWhitelist;
57 var $mDateFormat = null;
60 * Create "edit section" links?
62 var $mEditSection = true;
65 * Allow inclusion of special pages?
67 var $mAllowSpecialInclusion;
70 * Use tidy to cleanup output HTML?
75 * Which lang to call for PLURAL and GRAMMAR
77 var $mInterfaceMessage = false;
80 * Overrides $mInterfaceMessage with arbitrary language
82 var $mTargetLanguage = null;
85 * Maximum size of template expansions, in bytes
90 * Maximum number of nodes touched by PPFrame::expand()
95 * Maximum number of nodes generated by Preprocessor::preprocessToObj()
97 var $mMaxGeneratedPPNodeCount;
100 * Maximum recursion depth in PPFrame::expand()
102 var $mMaxPPExpandDepth;
105 * Maximum recursion depth for templates within templates
107 var $mMaxTemplateDepth;
110 * Maximum number of calls per parse to expensive parser functions
112 var $mExpensiveParserFunctionLimit;
115 * Remove HTML comments. ONLY APPLIES TO PREPROCESS OPERATIONS
117 var $mRemoveComments = true;
120 * Callback for template fetching. Used as first argument to call_user_func().
122 var $mTemplateCallback =
123 array( 'Parser', 'statelessFetchTemplate' );
126 * Enable limit report in an HTML comment on output
128 var $mEnableLimitReport = false;
131 * Timestamp used for {{CURRENTDAY}} etc.
136 * Target attribute for external links
138 var $mExternalLinkTarget;
141 * Clean up signature texts?
143 * 1) Strip ~~~, ~~~~ and ~~~~~ out of signatures
144 * 2) Substitute all transclusions
146 var $mCleanSignatures;
149 * Transform wiki markup when saving the page?
151 var $mPreSaveTransform = true;
154 * Whether content conversion should be disabled
156 var $mDisableContentConversion;
159 * Whether title conversion should be disabled
161 var $mDisableTitleConversion;
164 * Automatically number headings?
166 var $mNumberHeadings;
169 * Thumb size preferred by the user.
174 * Maximum article size of an article to be marked as "stub"
176 private $mStubThreshold;
179 * Language object of the User language.
190 * Parsing the page for a "preview" operation?
192 var $mIsPreview = false;
195 * Parsing the page for a "preview" operation on a single section?
197 var $mIsSectionPreview = false;
200 * Parsing the printable version of the page?
202 var $mIsPrintable = false;
205 * Extra key that should be present in the caching key.
210 * Function to be called when an option is accessed.
212 protected $onAccessCallback = null;
214 function getInterwikiMagic() {
215 return $this->mInterwikiMagic
;
218 function getAllowExternalImages() {
219 return $this->mAllowExternalImages
;
222 function getAllowExternalImagesFrom() {
223 return $this->mAllowExternalImagesFrom
;
226 function getEnableImageWhitelist() {
227 return $this->mEnableImageWhitelist
;
230 function getEditSection() {
231 return $this->mEditSection
;
234 function getNumberHeadings() {
235 $this->optionUsed( 'numberheadings' );
237 return $this->mNumberHeadings
;
240 function getAllowSpecialInclusion() {
241 return $this->mAllowSpecialInclusion
;
248 function getInterfaceMessage() {
249 return $this->mInterfaceMessage
;
252 function getTargetLanguage() {
253 return $this->mTargetLanguage
;
256 function getMaxIncludeSize() {
257 return $this->mMaxIncludeSize
;
260 function getMaxPPNodeCount() {
261 return $this->mMaxPPNodeCount
;
264 function getMaxGeneratedPPNodeCount() {
265 return $this->mMaxGeneratedPPNodeCount
;
268 function getMaxPPExpandDepth() {
269 return $this->mMaxPPExpandDepth
;
272 function getMaxTemplateDepth() {
273 return $this->mMaxTemplateDepth
;
277 function getExpensiveParserFunctionLimit() {
278 return $this->mExpensiveParserFunctionLimit
;
281 function getRemoveComments() {
282 return $this->mRemoveComments
;
285 function getTemplateCallback() {
286 return $this->mTemplateCallback
;
289 function getEnableLimitReport() {
290 return $this->mEnableLimitReport
;
293 function getCleanSignatures() {
294 return $this->mCleanSignatures
;
297 function getExternalLinkTarget() {
298 return $this->mExternalLinkTarget
;
301 function getDisableContentConversion() {
302 return $this->mDisableContentConversion
;
305 function getDisableTitleConversion() {
306 return $this->mDisableTitleConversion
;
309 function getThumbSize() {
310 $this->optionUsed( 'thumbsize' );
312 return $this->mThumbSize
;
315 function getStubThreshold() {
316 $this->optionUsed( 'stubthreshold' );
318 return $this->mStubThreshold
;
321 function getIsPreview() {
322 return $this->mIsPreview
;
325 function getIsSectionPreview() {
326 return $this->mIsSectionPreview
;
329 function getIsPrintable() {
330 $this->optionUsed( 'printable' );
332 return $this->mIsPrintable
;
339 function getPreSaveTransform() {
340 return $this->mPreSaveTransform
;
343 function getDateFormat() {
344 $this->optionUsed( 'dateformat' );
345 if ( !isset( $this->mDateFormat
) ) {
346 $this->mDateFormat
= $this->mUser
->getDatePreference();
348 return $this->mDateFormat
;
351 function getTimestamp() {
352 if ( !isset( $this->mTimestamp
) ) {
353 $this->mTimestamp
= wfTimestampNow();
355 return $this->mTimestamp
;
359 * Get the user language used by the parser for this page.
361 * You shouldn't use this. Really. $parser->getFunctionLang() is all you need.
363 * To avoid side-effects where the page will be rendered based on the language
364 * of the user who last saved, this function will triger a cache fragmentation.
365 * Usage of this method is discouraged for that reason.
367 * When saving, this will return the default language instead of the user's.
369 * {{int: }} uses this which used to produce inconsistent link tables (bug 14404).
374 function getUserLangObj() {
375 $this->optionUsed( 'userlang' );
376 return $this->mUserLang
;
380 * Same as getUserLangObj() but returns a string instead.
382 * @return string Language code
385 function getUserLang() {
386 return $this->getUserLangObj()->getCode();
389 function setInterwikiMagic( $x ) {
390 return wfSetVar( $this->mInterwikiMagic
, $x );
393 function setAllowExternalImages( $x ) {
394 return wfSetVar( $this->mAllowExternalImages
, $x );
397 function setAllowExternalImagesFrom( $x ) {
398 return wfSetVar( $this->mAllowExternalImagesFrom
, $x );
401 function setEnableImageWhitelist( $x ) {
402 return wfSetVar( $this->mEnableImageWhitelist
, $x );
405 function setDateFormat( $x ) {
406 return wfSetVar( $this->mDateFormat
, $x );
409 function setEditSection( $x ) {
410 return wfSetVar( $this->mEditSection
, $x );
413 function setNumberHeadings( $x ) {
414 return wfSetVar( $this->mNumberHeadings
, $x );
417 function setAllowSpecialInclusion( $x ) {
418 return wfSetVar( $this->mAllowSpecialInclusion
, $x );
421 function setTidy( $x ) {
422 return wfSetVar( $this->mTidy
, $x );
425 /** @deprecated since 1.19 */
426 function setSkin( $x ) {
427 wfDeprecated( __METHOD__
, '1.19' );
430 function setInterfaceMessage( $x ) {
431 return wfSetVar( $this->mInterfaceMessage
, $x );
434 function setTargetLanguage( $x ) {
435 return wfSetVar( $this->mTargetLanguage
, $x, true );
438 function setMaxIncludeSize( $x ) {
439 return wfSetVar( $this->mMaxIncludeSize
, $x );
442 function setMaxPPNodeCount( $x ) {
443 return wfSetVar( $this->mMaxPPNodeCount
, $x );
446 function setMaxGeneratedPPNodeCount( $x ) {
447 return wfSetVar( $this->mMaxGeneratedPPNodeCount
, $x );
450 function setMaxTemplateDepth( $x ) {
451 return wfSetVar( $this->mMaxTemplateDepth
, $x );
455 function setExpensiveParserFunctionLimit( $x ) {
456 return wfSetVar( $this->mExpensiveParserFunctionLimit
, $x );
459 function setRemoveComments( $x ) {
460 return wfSetVar( $this->mRemoveComments
, $x );
463 function setTemplateCallback( $x ) {
464 return wfSetVar( $this->mTemplateCallback
, $x );
467 function enableLimitReport( $x = true ) {
468 return wfSetVar( $this->mEnableLimitReport
, $x );
471 function setTimestamp( $x ) {
472 return wfSetVar( $this->mTimestamp
, $x );
475 function setCleanSignatures( $x ) {
476 return wfSetVar( $this->mCleanSignatures
, $x );
479 function setExternalLinkTarget( $x ) {
480 return wfSetVar( $this->mExternalLinkTarget
, $x );
483 function disableContentConversion( $x = true ) {
484 return wfSetVar( $this->mDisableContentConversion
, $x );
487 function disableTitleConversion( $x = true ) {
488 return wfSetVar( $this->mDisableTitleConversion
, $x );
491 function setUserLang( $x ) {
492 if ( is_string( $x ) ) {
493 $x = Language
::factory( $x );
496 return wfSetVar( $this->mUserLang
, $x );
499 function setThumbSize( $x ) {
500 return wfSetVar( $this->mThumbSize
, $x );
503 function setStubThreshold( $x ) {
504 return wfSetVar( $this->mStubThreshold
, $x );
507 function setPreSaveTransform( $x ) {
508 return wfSetVar( $this->mPreSaveTransform
, $x );
511 function setIsPreview( $x ) {
512 return wfSetVar( $this->mIsPreview
, $x );
515 function setIsSectionPreview( $x ) {
516 return wfSetVar( $this->mIsSectionPreview
, $x );
519 function setIsPrintable( $x ) {
520 return wfSetVar( $this->mIsPrintable
, $x );
524 * Extra key that should be present in the parser cache key.
526 function addExtraKey( $key ) {
527 $this->mExtraKey
.= '!' . $key;
533 * @param Language $lang
535 function __construct( $user = null, $lang = null ) {
536 if ( $user === null ) {
538 if ( $wgUser === null ) {
544 if ( $lang === null ) {
546 if ( !StubObject
::isRealObject( $wgLang ) ) {
551 $this->initialiseFromUser( $user, $lang );
555 * Get a ParserOptions object from a given user.
556 * Language will be taken from $wgLang.
559 * @return ParserOptions
561 public static function newFromUser( $user ) {
562 return new ParserOptions( $user );
566 * Get a ParserOptions object from a given user and language
569 * @param Language $lang
570 * @return ParserOptions
572 public static function newFromUserAndLang( User
$user, Language
$lang ) {
573 return new ParserOptions( $user, $lang );
577 * Get a ParserOptions object from a IContextSource object
579 * @param IContextSource $context
580 * @return ParserOptions
582 public static function newFromContext( IContextSource
$context ) {
583 return new ParserOptions( $context->getUser(), $context->getLanguage() );
590 * @param Language $lang
592 private function initialiseFromUser( $user, $lang ) {
593 global $wgInterwikiMagic, $wgAllowExternalImages,
594 $wgAllowExternalImagesFrom, $wgEnableImageWhitelist, $wgAllowSpecialInclusion,
595 $wgMaxArticleSize, $wgMaxPPNodeCount, $wgMaxTemplateDepth, $wgMaxPPExpandDepth,
596 $wgCleanSignatures, $wgExternalLinkTarget, $wgExpensiveParserFunctionLimit,
597 $wgMaxGeneratedPPNodeCount, $wgDisableLangConversion, $wgDisableTitleConversion;
599 wfProfileIn( __METHOD__
);
601 $this->mInterwikiMagic
= $wgInterwikiMagic;
602 $this->mAllowExternalImages
= $wgAllowExternalImages;
603 $this->mAllowExternalImagesFrom
= $wgAllowExternalImagesFrom;
604 $this->mEnableImageWhitelist
= $wgEnableImageWhitelist;
605 $this->mAllowSpecialInclusion
= $wgAllowSpecialInclusion;
606 $this->mMaxIncludeSize
= $wgMaxArticleSize * 1024;
607 $this->mMaxPPNodeCount
= $wgMaxPPNodeCount;
608 $this->mMaxGeneratedPPNodeCount
= $wgMaxGeneratedPPNodeCount;
609 $this->mMaxPPExpandDepth
= $wgMaxPPExpandDepth;
610 $this->mMaxTemplateDepth
= $wgMaxTemplateDepth;
611 $this->mExpensiveParserFunctionLimit
= $wgExpensiveParserFunctionLimit;
612 $this->mCleanSignatures
= $wgCleanSignatures;
613 $this->mExternalLinkTarget
= $wgExternalLinkTarget;
614 $this->mDisableContentConversion
= $wgDisableLangConversion;
615 $this->mDisableTitleConversion
= $wgDisableLangConversion ||
$wgDisableTitleConversion;
617 $this->mUser
= $user;
618 $this->mNumberHeadings
= $user->getOption( 'numberheadings' );
619 $this->mThumbSize
= $user->getOption( 'thumbsize' );
620 $this->mStubThreshold
= $user->getStubThreshold();
621 $this->mUserLang
= $lang;
623 wfProfileOut( __METHOD__
);
627 * Registers a callback for tracking which ParserOptions which are used.
628 * This is a private API with the parser.
629 * @param callable $callback
631 function registerWatcher( $callback ) {
632 $this->onAccessCallback
= $callback;
636 * Called when an option is accessed.
637 * @param string $optionName Name of the option
639 public function optionUsed( $optionName ) {
640 if ( $this->onAccessCallback
) {
641 call_user_func( $this->onAccessCallback
, $optionName );
646 * Returns the full array of options that would have been used by
648 * Used to get the old parser cache entries when available.
651 public static function legacyOptions() {
663 * Generate a hash string with the values set on these ParserOptions
664 * for the keys given in the array.
665 * This will be used as part of the hash key for the parser cache,
666 * so users sharign the options with vary for the same page share
667 * the same cached data safely.
669 * Extensions which require it should install 'PageRenderingHash' hook,
670 * which will give them a chance to modify this key based on their own
674 * @param array $forOptions
675 * @param Title $title Used to get the content language of the page (since r97636)
676 * @return string Page rendering hash
678 public function optionsHash( $forOptions, $title = null ) {
679 global $wgRenderHashAppend;
681 // FIXME: Once the cache key is reorganized this argument
682 // can be dropped. It was used when the math extension was
686 // Space assigned for the stubthreshold but unused
687 // since it disables the parser cache, its value will always
688 // be 0 when this function is called by parsercache.
689 if ( in_array( 'stubthreshold', $forOptions ) ) {
690 $confstr .= '!' . $this->mStubThreshold
;
695 if ( in_array( 'dateformat', $forOptions ) ) {
696 $confstr .= '!' . $this->getDateFormat();
699 if ( in_array( 'numberheadings', $forOptions ) ) {
700 $confstr .= '!' . ( $this->mNumberHeadings ?
'1' : '' );
705 if ( in_array( 'userlang', $forOptions ) ) {
706 $confstr .= '!' . $this->mUserLang
->getCode();
711 if ( in_array( 'thumbsize', $forOptions ) ) {
712 $confstr .= '!' . $this->mThumbSize
;
717 // add in language specific options, if any
718 // @todo FIXME: This is just a way of retrieving the url/user preferred variant
719 if ( !is_null( $title ) ) {
720 $confstr .= $title->getPageLanguage()->getExtraHashOptions();
723 $confstr .= $wgContLang->getExtraHashOptions();
726 $confstr .= $wgRenderHashAppend;
728 if ( !in_array( 'editsection', $forOptions ) ) {
730 } elseif ( !$this->mEditSection
) {
731 $confstr .= '!edit=0';
734 if ( $this->mIsPrintable
&& in_array( 'printable', $forOptions ) ) {
735 $confstr .= '!printable=1';
738 if ( $this->mExtraKey
!= '' ) {
739 $confstr .= $this->mExtraKey
;
742 // Give a chance for extensions to modify the hash, if they have
743 // extra options or other effects on the parser cache.
744 wfRunHooks( 'PageRenderingHash', array( &$confstr, $this->getUser(), &$forOptions ) );
746 // Make it a valid memcached key fragment
747 $confstr = str_replace( ' ', '_', $confstr );