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
37 public $mInterwikiMagic;
40 * Allow external images inline?
42 public $mAllowExternalImages;
45 * If not, any exception?
47 public $mAllowExternalImagesFrom;
50 * If not or it doesn't match, should we check an on-wiki whitelist?
52 public $mEnableImageWhitelist;
57 public $mDateFormat = null;
60 * Create "edit section" links?
62 public $mEditSection = true;
65 * Allow inclusion of special pages?
67 public $mAllowSpecialInclusion;
70 * Use tidy to cleanup output HTML?
72 public $mTidy = false;
75 * Which lang to call for PLURAL and GRAMMAR
77 public $mInterfaceMessage = false;
80 * Overrides $mInterfaceMessage with arbitrary language
82 public $mTargetLanguage = null;
85 * Maximum size of template expansions, in bytes
87 public $mMaxIncludeSize;
90 * Maximum number of nodes touched by PPFrame::expand()
92 public $mMaxPPNodeCount;
95 * Maximum number of nodes generated by Preprocessor::preprocessToObj()
97 public $mMaxGeneratedPPNodeCount;
100 * Maximum recursion depth in PPFrame::expand()
102 public $mMaxPPExpandDepth;
105 * Maximum recursion depth for templates within templates
107 public $mMaxTemplateDepth;
110 * Maximum number of calls per parse to expensive parser functions
112 public $mExpensiveParserFunctionLimit;
115 * Remove HTML comments. ONLY APPLIES TO PREPROCESS OPERATIONS
117 public $mRemoveComments = true;
120 * Callback for current revision fetching. Used as first argument to call_user_func().
122 public $mCurrentRevisionCallback =
123 array( 'Parser', 'statelessFetchRevision' );
126 * Callback for template fetching. Used as first argument to call_user_func().
128 public $mTemplateCallback =
129 array( 'Parser', 'statelessFetchTemplate' );
132 * Enable limit report in an HTML comment on output
134 public $mEnableLimitReport = false;
137 * Timestamp used for {{CURRENTDAY}} etc.
142 * Target attribute for external links
144 public $mExternalLinkTarget;
147 * Clean up signature texts?
149 * 1) Strip ~~~, ~~~~ and ~~~~~ out of signatures
150 * 2) Substitute all transclusions
152 public $mCleanSignatures;
155 * Transform wiki markup when saving the page?
157 public $mPreSaveTransform = true;
160 * Whether content conversion should be disabled
162 public $mDisableContentConversion;
165 * Whether title conversion should be disabled
167 public $mDisableTitleConversion;
170 * Automatically number headings?
172 public $mNumberHeadings;
175 * Thumb size preferred by the user.
180 * Maximum article size of an article to be marked as "stub"
182 private $mStubThreshold;
185 * Language object of the User language.
196 * Parsing the page for a "preview" operation?
198 public $mIsPreview = false;
201 * Parsing the page for a "preview" operation on a single section?
203 public $mIsSectionPreview = false;
206 * Parsing the printable version of the page?
208 public $mIsPrintable = false;
211 * Extra key that should be present in the caching key.
213 public $mExtraKey = '';
216 * Function to be called when an option is accessed.
218 protected $onAccessCallback = null;
221 * If the page being parsed is a redirect, this should hold the redirect
225 private $redirectTarget = null;
227 public function getInterwikiMagic() {
228 return $this->mInterwikiMagic
;
231 public function getAllowExternalImages() {
232 return $this->mAllowExternalImages
;
235 public function getAllowExternalImagesFrom() {
236 return $this->mAllowExternalImagesFrom
;
239 public function getEnableImageWhitelist() {
240 return $this->mEnableImageWhitelist
;
243 public function getEditSection() {
244 return $this->mEditSection
;
247 public function getNumberHeadings() {
248 $this->optionUsed( 'numberheadings' );
250 return $this->mNumberHeadings
;
253 public function getAllowSpecialInclusion() {
254 return $this->mAllowSpecialInclusion
;
257 public function getTidy() {
261 public function getInterfaceMessage() {
262 return $this->mInterfaceMessage
;
265 public function getTargetLanguage() {
266 return $this->mTargetLanguage
;
269 public function getMaxIncludeSize() {
270 return $this->mMaxIncludeSize
;
273 public function getMaxPPNodeCount() {
274 return $this->mMaxPPNodeCount
;
277 public function getMaxGeneratedPPNodeCount() {
278 return $this->mMaxGeneratedPPNodeCount
;
281 public function getMaxPPExpandDepth() {
282 return $this->mMaxPPExpandDepth
;
285 public function getMaxTemplateDepth() {
286 return $this->mMaxTemplateDepth
;
290 public function getExpensiveParserFunctionLimit() {
291 return $this->mExpensiveParserFunctionLimit
;
294 public function getRemoveComments() {
295 return $this->mRemoveComments
;
299 public function getCurrentRevisionCallback() {
300 return $this->mCurrentRevisionCallback
;
303 public function getTemplateCallback() {
304 return $this->mTemplateCallback
;
307 public function getEnableLimitReport() {
308 return $this->mEnableLimitReport
;
311 public function getCleanSignatures() {
312 return $this->mCleanSignatures
;
315 public function getExternalLinkTarget() {
316 return $this->mExternalLinkTarget
;
319 public function getDisableContentConversion() {
320 return $this->mDisableContentConversion
;
323 public function getDisableTitleConversion() {
324 return $this->mDisableTitleConversion
;
327 public function getThumbSize() {
328 $this->optionUsed( 'thumbsize' );
330 return $this->mThumbSize
;
333 public function getStubThreshold() {
334 $this->optionUsed( 'stubthreshold' );
336 return $this->mStubThreshold
;
339 public function getIsPreview() {
340 return $this->mIsPreview
;
343 public function getIsSectionPreview() {
344 return $this->mIsSectionPreview
;
347 public function getIsPrintable() {
348 $this->optionUsed( 'printable' );
350 return $this->mIsPrintable
;
353 public function getUser() {
357 public function getPreSaveTransform() {
358 return $this->mPreSaveTransform
;
361 public function getDateFormat() {
362 $this->optionUsed( 'dateformat' );
363 if ( !isset( $this->mDateFormat
) ) {
364 $this->mDateFormat
= $this->mUser
->getDatePreference();
366 return $this->mDateFormat
;
369 public function getTimestamp() {
370 if ( !isset( $this->mTimestamp
) ) {
371 $this->mTimestamp
= wfTimestampNow();
373 return $this->mTimestamp
;
377 * Get the user language used by the parser for this page.
379 * You shouldn't use this. Really. $parser->getFunctionLang() is all you need.
381 * To avoid side-effects where the page will be rendered based on the language
382 * of the user who last saved, this function will triger a cache fragmentation.
383 * Usage of this method is discouraged for that reason.
385 * When saving, this will return the default language instead of the user's.
387 * {{int: }} uses this which used to produce inconsistent link tables (bug 14404).
392 public function getUserLangObj() {
393 $this->optionUsed( 'userlang' );
394 return $this->mUserLang
;
398 * Same as getUserLangObj() but returns a string instead.
400 * @return string Language code
403 public function getUserLang() {
404 return $this->getUserLangObj()->getCode();
407 public function setInterwikiMagic( $x ) {
408 return wfSetVar( $this->mInterwikiMagic
, $x );
411 public function setAllowExternalImages( $x ) {
412 return wfSetVar( $this->mAllowExternalImages
, $x );
415 public function setAllowExternalImagesFrom( $x ) {
416 return wfSetVar( $this->mAllowExternalImagesFrom
, $x );
419 public function setEnableImageWhitelist( $x ) {
420 return wfSetVar( $this->mEnableImageWhitelist
, $x );
423 public function setDateFormat( $x ) {
424 return wfSetVar( $this->mDateFormat
, $x );
427 public function setEditSection( $x ) {
428 return wfSetVar( $this->mEditSection
, $x );
431 public function setNumberHeadings( $x ) {
432 return wfSetVar( $this->mNumberHeadings
, $x );
435 public function setAllowSpecialInclusion( $x ) {
436 return wfSetVar( $this->mAllowSpecialInclusion
, $x );
439 public function setTidy( $x ) {
440 return wfSetVar( $this->mTidy
, $x );
443 public function setInterfaceMessage( $x ) {
444 return wfSetVar( $this->mInterfaceMessage
, $x );
447 public function setTargetLanguage( $x ) {
448 return wfSetVar( $this->mTargetLanguage
, $x, true );
451 public function setMaxIncludeSize( $x ) {
452 return wfSetVar( $this->mMaxIncludeSize
, $x );
455 public function setMaxPPNodeCount( $x ) {
456 return wfSetVar( $this->mMaxPPNodeCount
, $x );
459 public function setMaxGeneratedPPNodeCount( $x ) {
460 return wfSetVar( $this->mMaxGeneratedPPNodeCount
, $x );
463 public function setMaxTemplateDepth( $x ) {
464 return wfSetVar( $this->mMaxTemplateDepth
, $x );
468 public function setExpensiveParserFunctionLimit( $x ) {
469 return wfSetVar( $this->mExpensiveParserFunctionLimit
, $x );
472 public function setRemoveComments( $x ) {
473 return wfSetVar( $this->mRemoveComments
, $x );
477 public function setCurrentRevisionCallback( $x ) {
478 return wfSetVar( $this->mCurrentRevisionCallback
, $x );
481 public function setTemplateCallback( $x ) {
482 return wfSetVar( $this->mTemplateCallback
, $x );
485 public function enableLimitReport( $x = true ) {
486 return wfSetVar( $this->mEnableLimitReport
, $x );
489 public function setTimestamp( $x ) {
490 return wfSetVar( $this->mTimestamp
, $x );
493 public function setCleanSignatures( $x ) {
494 return wfSetVar( $this->mCleanSignatures
, $x );
497 public function setExternalLinkTarget( $x ) {
498 return wfSetVar( $this->mExternalLinkTarget
, $x );
501 public function disableContentConversion( $x = true ) {
502 return wfSetVar( $this->mDisableContentConversion
, $x );
505 public function disableTitleConversion( $x = true ) {
506 return wfSetVar( $this->mDisableTitleConversion
, $x );
509 public function setUserLang( $x ) {
510 if ( is_string( $x ) ) {
511 $x = Language
::factory( $x );
514 return wfSetVar( $this->mUserLang
, $x );
517 public function setThumbSize( $x ) {
518 return wfSetVar( $this->mThumbSize
, $x );
521 public function setStubThreshold( $x ) {
522 return wfSetVar( $this->mStubThreshold
, $x );
525 public function setPreSaveTransform( $x ) {
526 return wfSetVar( $this->mPreSaveTransform
, $x );
529 public function setIsPreview( $x ) {
530 return wfSetVar( $this->mIsPreview
, $x );
533 public function setIsSectionPreview( $x ) {
534 return wfSetVar( $this->mIsSectionPreview
, $x );
537 public function setIsPrintable( $x ) {
538 return wfSetVar( $this->mIsPrintable
, $x );
542 * Set the redirect target.
544 * Note that setting or changing this does not *make* the page a redirect
545 * or change its target, it merely records the information for reference
549 * @param Title|null $title
551 function setRedirectTarget( $title ) {
552 $this->redirectTarget
= $title;
556 * Get the previously-set redirect target.
561 function getRedirectTarget() {
562 return $this->redirectTarget
;
566 * Extra key that should be present in the parser cache key.
569 public function addExtraKey( $key ) {
570 $this->mExtraKey
.= '!' . $key;
576 * @param Language $lang
578 public function __construct( $user = null, $lang = null ) {
579 if ( $user === null ) {
581 if ( $wgUser === null ) {
587 if ( $lang === null ) {
589 if ( !StubObject
::isRealObject( $wgLang ) ) {
594 $this->initialiseFromUser( $user, $lang );
598 * Get a ParserOptions object from a given user.
599 * Language will be taken from $wgLang.
602 * @return ParserOptions
604 public static function newFromUser( $user ) {
605 return new ParserOptions( $user );
609 * Get a ParserOptions object from a given user and language
612 * @param Language $lang
613 * @return ParserOptions
615 public static function newFromUserAndLang( User
$user, Language
$lang ) {
616 return new ParserOptions( $user, $lang );
620 * Get a ParserOptions object from a IContextSource object
622 * @param IContextSource $context
623 * @return ParserOptions
625 public static function newFromContext( IContextSource
$context ) {
626 return new ParserOptions( $context->getUser(), $context->getLanguage() );
633 * @param Language $lang
635 private function initialiseFromUser( $user, $lang ) {
636 global $wgInterwikiMagic, $wgAllowExternalImages,
637 $wgAllowExternalImagesFrom, $wgEnableImageWhitelist, $wgAllowSpecialInclusion,
638 $wgMaxArticleSize, $wgMaxPPNodeCount, $wgMaxTemplateDepth, $wgMaxPPExpandDepth,
639 $wgCleanSignatures, $wgExternalLinkTarget, $wgExpensiveParserFunctionLimit,
640 $wgMaxGeneratedPPNodeCount, $wgDisableLangConversion, $wgDisableTitleConversion;
642 wfProfileIn( __METHOD__
);
644 $this->mInterwikiMagic
= $wgInterwikiMagic;
645 $this->mAllowExternalImages
= $wgAllowExternalImages;
646 $this->mAllowExternalImagesFrom
= $wgAllowExternalImagesFrom;
647 $this->mEnableImageWhitelist
= $wgEnableImageWhitelist;
648 $this->mAllowSpecialInclusion
= $wgAllowSpecialInclusion;
649 $this->mMaxIncludeSize
= $wgMaxArticleSize * 1024;
650 $this->mMaxPPNodeCount
= $wgMaxPPNodeCount;
651 $this->mMaxGeneratedPPNodeCount
= $wgMaxGeneratedPPNodeCount;
652 $this->mMaxPPExpandDepth
= $wgMaxPPExpandDepth;
653 $this->mMaxTemplateDepth
= $wgMaxTemplateDepth;
654 $this->mExpensiveParserFunctionLimit
= $wgExpensiveParserFunctionLimit;
655 $this->mCleanSignatures
= $wgCleanSignatures;
656 $this->mExternalLinkTarget
= $wgExternalLinkTarget;
657 $this->mDisableContentConversion
= $wgDisableLangConversion;
658 $this->mDisableTitleConversion
= $wgDisableLangConversion ||
$wgDisableTitleConversion;
660 $this->mUser
= $user;
661 $this->mNumberHeadings
= $user->getOption( 'numberheadings' );
662 $this->mThumbSize
= $user->getOption( 'thumbsize' );
663 $this->mStubThreshold
= $user->getStubThreshold();
664 $this->mUserLang
= $lang;
666 wfProfileOut( __METHOD__
);
670 * Registers a callback for tracking which ParserOptions which are used.
671 * This is a private API with the parser.
672 * @param callable $callback
674 public function registerWatcher( $callback ) {
675 $this->onAccessCallback
= $callback;
679 * Called when an option is accessed.
680 * @param string $optionName Name of the option
682 public function optionUsed( $optionName ) {
683 if ( $this->onAccessCallback
) {
684 call_user_func( $this->onAccessCallback
, $optionName );
689 * Returns the full array of options that would have been used by
691 * Used to get the old parser cache entries when available.
694 public static function legacyOptions() {
706 * Generate a hash string with the values set on these ParserOptions
707 * for the keys given in the array.
708 * This will be used as part of the hash key for the parser cache,
709 * so users sharing the options with vary for the same page share
710 * the same cached data safely.
712 * Extensions which require it should install 'PageRenderingHash' hook,
713 * which will give them a chance to modify this key based on their own
717 * @param array $forOptions
718 * @param Title $title Used to get the content language of the page (since r97636)
719 * @return string Page rendering hash
721 public function optionsHash( $forOptions, $title = null ) {
722 global $wgRenderHashAppend;
724 // FIXME: Once the cache key is reorganized this argument
725 // can be dropped. It was used when the math extension was
729 // Space assigned for the stubthreshold but unused
730 // since it disables the parser cache, its value will always
731 // be 0 when this function is called by parsercache.
732 if ( in_array( 'stubthreshold', $forOptions ) ) {
733 $confstr .= '!' . $this->mStubThreshold
;
738 if ( in_array( 'dateformat', $forOptions ) ) {
739 $confstr .= '!' . $this->getDateFormat();
742 if ( in_array( 'numberheadings', $forOptions ) ) {
743 $confstr .= '!' . ( $this->mNumberHeadings ?
'1' : '' );
748 if ( in_array( 'userlang', $forOptions ) ) {
749 $confstr .= '!' . $this->mUserLang
->getCode();
754 if ( in_array( 'thumbsize', $forOptions ) ) {
755 $confstr .= '!' . $this->mThumbSize
;
760 // add in language specific options, if any
761 // @todo FIXME: This is just a way of retrieving the url/user preferred variant
762 if ( !is_null( $title ) ) {
763 $confstr .= $title->getPageLanguage()->getExtraHashOptions();
766 $confstr .= $wgContLang->getExtraHashOptions();
769 $confstr .= $wgRenderHashAppend;
771 if ( !in_array( 'editsection', $forOptions ) ) {
773 } elseif ( !$this->mEditSection
) {
774 $confstr .= '!edit=0';
777 if ( $this->mIsPrintable
&& in_array( 'printable', $forOptions ) ) {
778 $confstr .= '!printable=1';
781 if ( $this->mExtraKey
!= '' ) {
782 $confstr .= $this->mExtraKey
;
785 // Give a chance for extensions to modify the hash, if they have
786 // extra options or other effects on the parser cache.
787 wfRunHooks( 'PageRenderingHash', array( &$confstr, $this->getUser(), &$forOptions ) );
789 // Make it a valid memcached key fragment
790 $confstr = str_replace( ' ', '_', $confstr );