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.
33 /** @var bool Parsing the page for a "preview" operation? */
34 public $mIsPreview = false;
36 /** @var bool Interlanguage links are removed and returned in an array */
37 protected $mInterwikiMagic;
39 /** @var bool Allow external images inline? */
40 protected $mAllowExternalImages;
42 /** @var string|array If not, any exception? */
43 protected $mAllowExternalImagesFrom;
45 /** @var bool If not or it doesn't match, should we check an on-wiki whitelist? */
46 protected $mEnableImageWhitelist;
48 /** @var string Date format index */
49 protected $mDateFormat = null;
51 /** @var bool Create "edit section" links? */
52 protected $mEditSection = true;
54 /** @var bool Allow inclusion of special pages? */
55 protected $mAllowSpecialInclusion;
57 /** @var bool Use tidy to cleanup output HTML? */
58 protected $mTidy = false;
61 * @var bool Which lang to call for PLURAL and GRAMMAR
62 * @todo FIXME: This comment doesn't appear to be correct.
63 * Should be this? Whether this is an interface message.
65 protected $mInterfaceMessage = false;
67 /** @var string|Language Overrides $mInterfaceMessage with arbitrary language */
68 protected $mTargetLanguage = null;
70 /** @var int Maximum size of template expansions, in bytes */
71 protected $mMaxIncludeSize;
73 /** @var int Maximum number of nodes touched by PPFrame::expand() */
74 protected $mMaxPPNodeCount;
76 /** @var int Maximum number of nodes generated by Preprocessor::preprocessToObj() */
77 protected $mMaxGeneratedPPNodeCount;
79 /** @var int Maximum recursion depth in PPFrame::expand() */
80 protected $mMaxPPExpandDepth;
82 /** @var int Maximum recursion depth for templates within templates */
83 protected $mMaxTemplateDepth;
85 /** @var int Maximum number of calls per parse to expensive parser functions */
86 protected $mExpensiveParserFunctionLimit;
88 /** @var bool Remove HTML comments. ONLY APPLIES TO PREPROCESS OPERATIONS */
89 protected $mRemoveComments = true;
91 /** @var array Callback for template fetching. Used as first argument to call_user_func(). */
92 protected $mTemplateCallback = array( 'Parser', 'statelessFetchTemplate' );
94 /** @var bool Enable limit report in an HTML comment on output */
95 protected $mEnableLimitReport = false;
97 /** @var string Timestamp used for {{CURRENTDAY}} etc. */
98 protected $mTimestamp;
100 /** @var bool|string Target attribute for external links */
101 protected $mExternalLinkTarget;
104 * @var bool Clean up signature texts?
106 * 1) Strip ~~~, ~~~~ and ~~~~~ out of signatures
107 * 2) Substitute all transclusions
109 protected $mCleanSignatures;
111 /** @var bool Transform wiki markup when saving the page? */
112 protected $mPreSaveTransform = true;
114 /** @var bool Whether content conversion should be disabled */
115 protected $mDisableContentConversion;
117 /** @var bool Whether title conversion should be disabled */
118 protected $mDisableTitleConversion;
120 /** @var string Automatically number headings? */
121 protected $mNumberHeadings;
123 /** @var string Thumb size preferred by the user. */
124 protected $mThumbSize;
126 /** @var Language Language object of the User language. */
127 protected $mUserLang;
129 /** @var User Stored user object */
132 /** @var bool Parsing the page for a "preview" operation on a single section? */
133 protected $mIsSectionPreview = false;
135 /** @var bool Parsing the printable version of the page? */
136 protected $mIsPrintable = false;
138 /** @var string Extra key that should be present in the caching key. */
139 protected $mExtraKey = '';
141 /** @var callable Function to be called when an option is accessed. */
142 protected $onAccessCallback = null;
144 /** @var int Maximum article size of an article to be marked as "stub" */
145 private $mStubThreshold;
147 function getInterwikiMagic() {
148 return $this->mInterwikiMagic
;
151 function getAllowExternalImages() {
152 return $this->mAllowExternalImages
;
155 function getAllowExternalImagesFrom() {
156 return $this->mAllowExternalImagesFrom
;
159 function getEnableImageWhitelist() {
160 return $this->mEnableImageWhitelist
;
163 function getEditSection() {
164 return $this->mEditSection
;
167 function getNumberHeadings() {
168 $this->optionUsed( 'numberheadings' );
170 return $this->mNumberHeadings
;
173 function getAllowSpecialInclusion() {
174 return $this->mAllowSpecialInclusion
;
181 function getInterfaceMessage() {
182 return $this->mInterfaceMessage
;
185 function getTargetLanguage() {
186 return $this->mTargetLanguage
;
189 function getMaxIncludeSize() {
190 return $this->mMaxIncludeSize
;
193 function getMaxPPNodeCount() {
194 return $this->mMaxPPNodeCount
;
197 function getMaxGeneratedPPNodeCount() {
198 return $this->mMaxGeneratedPPNodeCount
;
201 function getMaxPPExpandDepth() {
202 return $this->mMaxPPExpandDepth
;
205 function getMaxTemplateDepth() {
206 return $this->mMaxTemplateDepth
;
210 function getExpensiveParserFunctionLimit() {
211 return $this->mExpensiveParserFunctionLimit
;
214 function getRemoveComments() {
215 return $this->mRemoveComments
;
218 function getTemplateCallback() {
219 return $this->mTemplateCallback
;
222 function getEnableLimitReport() {
223 return $this->mEnableLimitReport
;
226 function getCleanSignatures() {
227 return $this->mCleanSignatures
;
230 function getExternalLinkTarget() {
231 return $this->mExternalLinkTarget
;
234 function getDisableContentConversion() {
235 return $this->mDisableContentConversion
;
238 function getDisableTitleConversion() {
239 return $this->mDisableTitleConversion
;
242 function getThumbSize() {
243 $this->optionUsed( 'thumbsize' );
245 return $this->mThumbSize
;
248 function getStubThreshold() {
249 $this->optionUsed( 'stubthreshold' );
251 return $this->mStubThreshold
;
254 function getIsPreview() {
255 return $this->mIsPreview
;
258 function getIsSectionPreview() {
259 return $this->mIsSectionPreview
;
262 function getIsPrintable() {
263 $this->optionUsed( 'printable' );
265 return $this->mIsPrintable
;
272 function getPreSaveTransform() {
273 return $this->mPreSaveTransform
;
276 function getDateFormat() {
277 $this->optionUsed( 'dateformat' );
278 if ( !isset( $this->mDateFormat
) ) {
279 $this->mDateFormat
= $this->mUser
->getDatePreference();
281 return $this->mDateFormat
;
284 function getTimestamp() {
285 if ( !isset( $this->mTimestamp
) ) {
286 $this->mTimestamp
= wfTimestampNow();
288 return $this->mTimestamp
;
292 * Get the user language used by the parser for this page.
294 * You shouldn't use this. Really. $parser->getFunctionLang() is all you need.
296 * To avoid side-effects where the page will be rendered based on the language
297 * of the user who last saved, this function will triger a cache fragmentation.
298 * Usage of this method is discouraged for that reason.
300 * When saving, this will return the default language instead of the user's.
302 * {{int: }} uses this which used to produce inconsistent link tables (bug 14404).
307 function getUserLangObj() {
308 $this->optionUsed( 'userlang' );
309 return $this->mUserLang
;
313 * Same as getUserLangObj() but returns a string instead.
315 * @return string Language code
318 function getUserLang() {
319 return $this->getUserLangObj()->getCode();
322 function setInterwikiMagic( $x ) {
323 return wfSetVar( $this->mInterwikiMagic
, $x );
326 function setAllowExternalImages( $x ) {
327 return wfSetVar( $this->mAllowExternalImages
, $x );
330 function setAllowExternalImagesFrom( $x ) {
331 return wfSetVar( $this->mAllowExternalImagesFrom
, $x );
334 function setEnableImageWhitelist( $x ) {
335 return wfSetVar( $this->mEnableImageWhitelist
, $x );
338 function setDateFormat( $x ) {
339 return wfSetVar( $this->mDateFormat
, $x );
342 function setEditSection( $x ) {
343 return wfSetVar( $this->mEditSection
, $x );
346 function setNumberHeadings( $x ) {
347 return wfSetVar( $this->mNumberHeadings
, $x );
350 function setAllowSpecialInclusion( $x ) {
351 return wfSetVar( $this->mAllowSpecialInclusion
, $x );
354 function setTidy( $x ) {
355 return wfSetVar( $this->mTidy
, $x );
358 /** @deprecated since 1.19 */
359 function setSkin( $x ) {
360 wfDeprecated( __METHOD__
, '1.19' );
363 function setInterfaceMessage( $x ) {
364 return wfSetVar( $this->mInterfaceMessage
, $x );
367 function setTargetLanguage( $x ) {
368 return wfSetVar( $this->mTargetLanguage
, $x, true );
371 function setMaxIncludeSize( $x ) {
372 return wfSetVar( $this->mMaxIncludeSize
, $x );
375 function setMaxPPNodeCount( $x ) {
376 return wfSetVar( $this->mMaxPPNodeCount
, $x );
379 function setMaxGeneratedPPNodeCount( $x ) {
380 return wfSetVar( $this->mMaxGeneratedPPNodeCount
, $x );
383 function setMaxTemplateDepth( $x ) {
384 return wfSetVar( $this->mMaxTemplateDepth
, $x );
388 function setExpensiveParserFunctionLimit( $x ) {
389 return wfSetVar( $this->mExpensiveParserFunctionLimit
, $x );
392 function setRemoveComments( $x ) {
393 return wfSetVar( $this->mRemoveComments
, $x );
396 function setTemplateCallback( $x ) {
397 return wfSetVar( $this->mTemplateCallback
, $x );
400 function enableLimitReport( $x = true ) {
401 return wfSetVar( $this->mEnableLimitReport
, $x );
404 function setTimestamp( $x ) {
405 return wfSetVar( $this->mTimestamp
, $x );
408 function setCleanSignatures( $x ) {
409 return wfSetVar( $this->mCleanSignatures
, $x );
412 function setExternalLinkTarget( $x ) {
413 return wfSetVar( $this->mExternalLinkTarget
, $x );
416 function disableContentConversion( $x = true ) {
417 return wfSetVar( $this->mDisableContentConversion
, $x );
420 function disableTitleConversion( $x = true ) {
421 return wfSetVar( $this->mDisableTitleConversion
, $x );
424 function setUserLang( $x ) {
425 if ( is_string( $x ) ) {
426 $x = Language
::factory( $x );
429 return wfSetVar( $this->mUserLang
, $x );
432 function setThumbSize( $x ) {
433 return wfSetVar( $this->mThumbSize
, $x );
436 function setStubThreshold( $x ) {
437 return wfSetVar( $this->mStubThreshold
, $x );
440 function setPreSaveTransform( $x ) {
441 return wfSetVar( $this->mPreSaveTransform
, $x );
444 function setIsPreview( $x ) {
445 return wfSetVar( $this->mIsPreview
, $x );
448 function setIsSectionPreview( $x ) {
449 return wfSetVar( $this->mIsSectionPreview
, $x );
452 function setIsPrintable( $x ) {
453 return wfSetVar( $this->mIsPrintable
, $x );
457 * Extra key that should be present in the parser cache key.
459 function addExtraKey( $key ) {
460 $this->mExtraKey
.= '!' . $key;
466 * @param Language $lang
468 function __construct( $user = null, $lang = null ) {
469 if ( $user === null ) {
471 if ( $wgUser === null ) {
477 if ( $lang === null ) {
479 if ( !StubObject
::isRealObject( $wgLang ) ) {
484 $this->initialiseFromUser( $user, $lang );
488 * Get a ParserOptions object from a given user.
489 * Language will be taken from $wgLang.
492 * @return ParserOptions
494 public static function newFromUser( $user ) {
495 return new ParserOptions( $user );
499 * Get a ParserOptions object from a given user and language
502 * @param Language $lang
503 * @return ParserOptions
505 public static function newFromUserAndLang( User
$user, Language
$lang ) {
506 return new ParserOptions( $user, $lang );
510 * Get a ParserOptions object from a IContextSource object
512 * @param IContextSource $context
513 * @return ParserOptions
515 public static function newFromContext( IContextSource
$context ) {
516 return new ParserOptions( $context->getUser(), $context->getLanguage() );
523 * @param Language $lang
525 private function initialiseFromUser( $user, $lang ) {
526 global $wgInterwikiMagic, $wgAllowExternalImages,
527 $wgAllowExternalImagesFrom, $wgEnableImageWhitelist, $wgAllowSpecialInclusion,
528 $wgMaxArticleSize, $wgMaxPPNodeCount, $wgMaxTemplateDepth, $wgMaxPPExpandDepth,
529 $wgCleanSignatures, $wgExternalLinkTarget, $wgExpensiveParserFunctionLimit,
530 $wgMaxGeneratedPPNodeCount, $wgDisableLangConversion, $wgDisableTitleConversion;
532 wfProfileIn( __METHOD__
);
534 $this->mInterwikiMagic
= $wgInterwikiMagic;
535 $this->mAllowExternalImages
= $wgAllowExternalImages;
536 $this->mAllowExternalImagesFrom
= $wgAllowExternalImagesFrom;
537 $this->mEnableImageWhitelist
= $wgEnableImageWhitelist;
538 $this->mAllowSpecialInclusion
= $wgAllowSpecialInclusion;
539 $this->mMaxIncludeSize
= $wgMaxArticleSize * 1024;
540 $this->mMaxPPNodeCount
= $wgMaxPPNodeCount;
541 $this->mMaxGeneratedPPNodeCount
= $wgMaxGeneratedPPNodeCount;
542 $this->mMaxPPExpandDepth
= $wgMaxPPExpandDepth;
543 $this->mMaxTemplateDepth
= $wgMaxTemplateDepth;
544 $this->mExpensiveParserFunctionLimit
= $wgExpensiveParserFunctionLimit;
545 $this->mCleanSignatures
= $wgCleanSignatures;
546 $this->mExternalLinkTarget
= $wgExternalLinkTarget;
547 $this->mDisableContentConversion
= $wgDisableLangConversion;
548 $this->mDisableTitleConversion
= $wgDisableLangConversion ||
$wgDisableTitleConversion;
550 $this->mUser
= $user;
551 $this->mNumberHeadings
= $user->getOption( 'numberheadings' );
552 $this->mThumbSize
= $user->getOption( 'thumbsize' );
553 $this->mStubThreshold
= $user->getStubThreshold();
554 $this->mUserLang
= $lang;
556 wfProfileOut( __METHOD__
);
560 * Registers a callback for tracking which ParserOptions which are used.
561 * This is a private API with the parser.
562 * @param callable $callback
564 function registerWatcher( $callback ) {
565 $this->onAccessCallback
= $callback;
569 * Called when an option is accessed.
570 * @param string $optionName Name of the option
572 public function optionUsed( $optionName ) {
573 if ( $this->onAccessCallback
) {
574 call_user_func( $this->onAccessCallback
, $optionName );
579 * Returns the full array of options that would have been used by
581 * Used to get the old parser cache entries when available.
584 public static function legacyOptions() {
596 * Generate a hash string with the values set on these ParserOptions
597 * for the keys given in the array.
598 * This will be used as part of the hash key for the parser cache,
599 * so users sharign the options with vary for the same page share
600 * the same cached data safely.
602 * Extensions which require it should install 'PageRenderingHash' hook,
603 * which will give them a chance to modify this key based on their own
607 * @param array $forOptions
608 * @param Title $title Used to get the content language of the page (since r97636)
609 * @return string Page rendering hash
611 public function optionsHash( $forOptions, $title = null ) {
612 global $wgRenderHashAppend;
614 // FIXME: Once the cache key is reorganized this argument
615 // can be dropped. It was used when the math extension was
619 // Space assigned for the stubthreshold but unused
620 // since it disables the parser cache, its value will always
621 // be 0 when this function is called by parsercache.
622 if ( in_array( 'stubthreshold', $forOptions ) ) {
623 $confstr .= '!' . $this->mStubThreshold
;
628 if ( in_array( 'dateformat', $forOptions ) ) {
629 $confstr .= '!' . $this->getDateFormat();
632 if ( in_array( 'numberheadings', $forOptions ) ) {
633 $confstr .= '!' . ( $this->mNumberHeadings ?
'1' : '' );
638 if ( in_array( 'userlang', $forOptions ) ) {
639 $confstr .= '!' . $this->mUserLang
->getCode();
644 if ( in_array( 'thumbsize', $forOptions ) ) {
645 $confstr .= '!' . $this->mThumbSize
;
650 // add in language specific options, if any
651 // @todo FIXME: This is just a way of retrieving the url/user preferred variant
652 if ( !is_null( $title ) ) {
653 $confstr .= $title->getPageLanguage()->getExtraHashOptions();
656 $confstr .= $wgContLang->getExtraHashOptions();
659 $confstr .= $wgRenderHashAppend;
661 if ( !in_array( 'editsection', $forOptions ) ) {
663 } elseif ( !$this->mEditSection
) {
664 $confstr .= '!edit=0';
667 if ( $this->mIsPrintable
&& in_array( 'printable', $forOptions ) ) {
668 $confstr .= '!printable=1';
671 if ( $this->mExtraKey
!= '' ) {
672 $confstr .= $this->mExtraKey
;
675 // Give a chance for extensions to modify the hash, if they have
676 // extra options or other effects on the parser cache.
677 wfRunHooks( 'PageRenderingHash', array( &$confstr, $this->getUser(), &$forOptions ) );
679 // Make it a valid memcached key fragment
680 $confstr = str_replace( ' ', '_', $confstr );