Merge "Several tweaks to the install.php script"
[lhc/web/wiklou.git] / includes / parser / ParserOptions.php
1 <?php
2 /**
3 * Options for the PHP parser
4 *
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.
9 *
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.
14 *
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
19 *
20 * @file
21 * @ingroup Parser
22 */
23
24 /**
25 * \brief Set options of the Parser
26 *
27 * All member variables are supposed to be private in theory, although in
28 * practise this is not the case.
29 *
30 * @ingroup Parser
31 */
32 class ParserOptions {
33 /** @var bool Parsing the page for a "preview" operation? */
34 public $mIsPreview = false;
35
36 /** @var bool Interlanguage links are removed and returned in an array */
37 protected $mInterwikiMagic;
38
39 /** @var bool Allow external images inline? */
40 protected $mAllowExternalImages;
41
42 /** @var string|array If not, any exception? */
43 protected $mAllowExternalImagesFrom;
44
45 /** @var bool If not or it doesn't match, should we check an on-wiki whitelist? */
46 protected $mEnableImageWhitelist;
47
48 /** @var string Date format index */
49 protected $mDateFormat = null;
50
51 /** @var bool Create "edit section" links? */
52 protected $mEditSection = true;
53
54 /** @var bool Allow inclusion of special pages? */
55 protected $mAllowSpecialInclusion;
56
57 /** @var bool Use tidy to cleanup output HTML? */
58 protected $mTidy = false;
59
60 /**
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.
64 */
65 protected $mInterfaceMessage = false;
66
67 /** @var string|Language Overrides $mInterfaceMessage with arbitrary language */
68 protected $mTargetLanguage = null;
69
70 /** @var int Maximum size of template expansions, in bytes */
71 protected $mMaxIncludeSize;
72
73 /** @var int Maximum number of nodes touched by PPFrame::expand() */
74 protected $mMaxPPNodeCount;
75
76 /** @var int Maximum number of nodes generated by Preprocessor::preprocessToObj() */
77 protected $mMaxGeneratedPPNodeCount;
78
79 /** @var int Maximum recursion depth in PPFrame::expand() */
80 protected $mMaxPPExpandDepth;
81
82 /** @var int Maximum recursion depth for templates within templates */
83 protected $mMaxTemplateDepth;
84
85 /** @var int Maximum number of calls per parse to expensive parser functions */
86 protected $mExpensiveParserFunctionLimit;
87
88 /** @var bool Remove HTML comments. ONLY APPLIES TO PREPROCESS OPERATIONS */
89 protected $mRemoveComments = true;
90
91 /** @var array Callback for template fetching. Used as first argument to call_user_func(). */
92 protected $mTemplateCallback = array( 'Parser', 'statelessFetchTemplate' );
93
94 /** @var bool Enable limit report in an HTML comment on output */
95 protected $mEnableLimitReport = false;
96
97 /** @var string Timestamp used for {{CURRENTDAY}} etc. */
98 protected $mTimestamp;
99
100 /** @var bool|string Target attribute for external links */
101 protected $mExternalLinkTarget;
102
103 /**
104 * @var bool Clean up signature texts?
105 *
106 * 1) Strip ~~~, ~~~~ and ~~~~~ out of signatures
107 * 2) Substitute all transclusions
108 */
109 protected $mCleanSignatures;
110
111 /** @var bool Transform wiki markup when saving the page? */
112 protected $mPreSaveTransform = true;
113
114 /** @var bool Whether content conversion should be disabled */
115 protected $mDisableContentConversion;
116
117 /** @var bool Whether title conversion should be disabled */
118 protected $mDisableTitleConversion;
119
120 /** @var string Automatically number headings? */
121 protected $mNumberHeadings;
122
123 /** @var string Thumb size preferred by the user. */
124 protected $mThumbSize;
125
126 /** @var Language Language object of the User language. */
127 protected $mUserLang;
128
129 /** @var User Stored user object */
130 protected $mUser;
131
132 /** @var bool Parsing the page for a "preview" operation on a single section? */
133 protected $mIsSectionPreview = false;
134
135 /** @var bool Parsing the printable version of the page? */
136 protected $mIsPrintable = false;
137
138 /** @var string Extra key that should be present in the caching key. */
139 protected $mExtraKey = '';
140
141 /** @var callable Function to be called when an option is accessed. */
142 protected $onAccessCallback = null;
143
144 /** @var int Maximum article size of an article to be marked as "stub" */
145 private $mStubThreshold;
146
147 function getInterwikiMagic() {
148 return $this->mInterwikiMagic;
149 }
150
151 function getAllowExternalImages() {
152 return $this->mAllowExternalImages;
153 }
154
155 function getAllowExternalImagesFrom() {
156 return $this->mAllowExternalImagesFrom;
157 }
158
159 function getEnableImageWhitelist() {
160 return $this->mEnableImageWhitelist;
161 }
162
163 function getEditSection() {
164 return $this->mEditSection;
165 }
166
167 function getNumberHeadings() {
168 $this->optionUsed( 'numberheadings' );
169
170 return $this->mNumberHeadings;
171 }
172
173 function getAllowSpecialInclusion() {
174 return $this->mAllowSpecialInclusion;
175 }
176
177 function getTidy() {
178 return $this->mTidy;
179 }
180
181 function getInterfaceMessage() {
182 return $this->mInterfaceMessage;
183 }
184
185 function getTargetLanguage() {
186 return $this->mTargetLanguage;
187 }
188
189 function getMaxIncludeSize() {
190 return $this->mMaxIncludeSize;
191 }
192
193 function getMaxPPNodeCount() {
194 return $this->mMaxPPNodeCount;
195 }
196
197 function getMaxGeneratedPPNodeCount() {
198 return $this->mMaxGeneratedPPNodeCount;
199 }
200
201 function getMaxPPExpandDepth() {
202 return $this->mMaxPPExpandDepth;
203 }
204
205 function getMaxTemplateDepth() {
206 return $this->mMaxTemplateDepth;
207 }
208
209 /* @since 1.20 */
210 function getExpensiveParserFunctionLimit() {
211 return $this->mExpensiveParserFunctionLimit;
212 }
213
214 function getRemoveComments() {
215 return $this->mRemoveComments;
216 }
217
218 function getTemplateCallback() {
219 return $this->mTemplateCallback;
220 }
221
222 function getEnableLimitReport() {
223 return $this->mEnableLimitReport;
224 }
225
226 function getCleanSignatures() {
227 return $this->mCleanSignatures;
228 }
229
230 function getExternalLinkTarget() {
231 return $this->mExternalLinkTarget;
232 }
233
234 function getDisableContentConversion() {
235 return $this->mDisableContentConversion;
236 }
237
238 function getDisableTitleConversion() {
239 return $this->mDisableTitleConversion;
240 }
241
242 function getThumbSize() {
243 $this->optionUsed( 'thumbsize' );
244
245 return $this->mThumbSize;
246 }
247
248 function getStubThreshold() {
249 $this->optionUsed( 'stubthreshold' );
250
251 return $this->mStubThreshold;
252 }
253
254 function getIsPreview() {
255 return $this->mIsPreview;
256 }
257
258 function getIsSectionPreview() {
259 return $this->mIsSectionPreview;
260 }
261
262 function getIsPrintable() {
263 $this->optionUsed( 'printable' );
264
265 return $this->mIsPrintable;
266 }
267
268 function getUser() {
269 return $this->mUser;
270 }
271
272 function getPreSaveTransform() {
273 return $this->mPreSaveTransform;
274 }
275
276 function getDateFormat() {
277 $this->optionUsed( 'dateformat' );
278 if ( !isset( $this->mDateFormat ) ) {
279 $this->mDateFormat = $this->mUser->getDatePreference();
280 }
281 return $this->mDateFormat;
282 }
283
284 function getTimestamp() {
285 if ( !isset( $this->mTimestamp ) ) {
286 $this->mTimestamp = wfTimestampNow();
287 }
288 return $this->mTimestamp;
289 }
290
291 /**
292 * Get the user language used by the parser for this page.
293 *
294 * You shouldn't use this. Really. $parser->getFunctionLang() is all you need.
295 *
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.
299 *
300 * When saving, this will return the default language instead of the user's.
301 *
302 * {{int: }} uses this which used to produce inconsistent link tables (bug 14404).
303 *
304 * @return Language
305 * @since 1.19
306 */
307 function getUserLangObj() {
308 $this->optionUsed( 'userlang' );
309 return $this->mUserLang;
310 }
311
312 /**
313 * Same as getUserLangObj() but returns a string instead.
314 *
315 * @return string Language code
316 * @since 1.17
317 */
318 function getUserLang() {
319 return $this->getUserLangObj()->getCode();
320 }
321
322 function setInterwikiMagic( $x ) {
323 return wfSetVar( $this->mInterwikiMagic, $x );
324 }
325
326 function setAllowExternalImages( $x ) {
327 return wfSetVar( $this->mAllowExternalImages, $x );
328 }
329
330 function setAllowExternalImagesFrom( $x ) {
331 return wfSetVar( $this->mAllowExternalImagesFrom, $x );
332 }
333
334 function setEnableImageWhitelist( $x ) {
335 return wfSetVar( $this->mEnableImageWhitelist, $x );
336 }
337
338 function setDateFormat( $x ) {
339 return wfSetVar( $this->mDateFormat, $x );
340 }
341
342 function setEditSection( $x ) {
343 return wfSetVar( $this->mEditSection, $x );
344 }
345
346 function setNumberHeadings( $x ) {
347 return wfSetVar( $this->mNumberHeadings, $x );
348 }
349
350 function setAllowSpecialInclusion( $x ) {
351 return wfSetVar( $this->mAllowSpecialInclusion, $x );
352 }
353
354 function setTidy( $x ) {
355 return wfSetVar( $this->mTidy, $x );
356 }
357
358 /** @deprecated since 1.19 */
359 function setSkin( $x ) {
360 wfDeprecated( __METHOD__, '1.19' );
361 }
362
363 function setInterfaceMessage( $x ) {
364 return wfSetVar( $this->mInterfaceMessage, $x );
365 }
366
367 function setTargetLanguage( $x ) {
368 return wfSetVar( $this->mTargetLanguage, $x, true );
369 }
370
371 function setMaxIncludeSize( $x ) {
372 return wfSetVar( $this->mMaxIncludeSize, $x );
373 }
374
375 function setMaxPPNodeCount( $x ) {
376 return wfSetVar( $this->mMaxPPNodeCount, $x );
377 }
378
379 function setMaxGeneratedPPNodeCount( $x ) {
380 return wfSetVar( $this->mMaxGeneratedPPNodeCount, $x );
381 }
382
383 function setMaxTemplateDepth( $x ) {
384 return wfSetVar( $this->mMaxTemplateDepth, $x );
385 }
386
387 /* @since 1.20 */
388 function setExpensiveParserFunctionLimit( $x ) {
389 return wfSetVar( $this->mExpensiveParserFunctionLimit, $x );
390 }
391
392 function setRemoveComments( $x ) {
393 return wfSetVar( $this->mRemoveComments, $x );
394 }
395
396 function setTemplateCallback( $x ) {
397 return wfSetVar( $this->mTemplateCallback, $x );
398 }
399
400 function enableLimitReport( $x = true ) {
401 return wfSetVar( $this->mEnableLimitReport, $x );
402 }
403
404 function setTimestamp( $x ) {
405 return wfSetVar( $this->mTimestamp, $x );
406 }
407
408 function setCleanSignatures( $x ) {
409 return wfSetVar( $this->mCleanSignatures, $x );
410 }
411
412 function setExternalLinkTarget( $x ) {
413 return wfSetVar( $this->mExternalLinkTarget, $x );
414 }
415
416 function disableContentConversion( $x = true ) {
417 return wfSetVar( $this->mDisableContentConversion, $x );
418 }
419
420 function disableTitleConversion( $x = true ) {
421 return wfSetVar( $this->mDisableTitleConversion, $x );
422 }
423
424 function setUserLang( $x ) {
425 if ( is_string( $x ) ) {
426 $x = Language::factory( $x );
427 }
428
429 return wfSetVar( $this->mUserLang, $x );
430 }
431
432 function setThumbSize( $x ) {
433 return wfSetVar( $this->mThumbSize, $x );
434 }
435
436 function setStubThreshold( $x ) {
437 return wfSetVar( $this->mStubThreshold, $x );
438 }
439
440 function setPreSaveTransform( $x ) {
441 return wfSetVar( $this->mPreSaveTransform, $x );
442 }
443
444 function setIsPreview( $x ) {
445 return wfSetVar( $this->mIsPreview, $x );
446 }
447
448 function setIsSectionPreview( $x ) {
449 return wfSetVar( $this->mIsSectionPreview, $x );
450 }
451
452 function setIsPrintable( $x ) {
453 return wfSetVar( $this->mIsPrintable, $x );
454 }
455
456 /**
457 * Extra key that should be present in the parser cache key.
458 */
459 function addExtraKey( $key ) {
460 $this->mExtraKey .= '!' . $key;
461 }
462
463 /**
464 * Constructor
465 * @param User $user
466 * @param Language $lang
467 */
468 function __construct( $user = null, $lang = null ) {
469 if ( $user === null ) {
470 global $wgUser;
471 if ( $wgUser === null ) {
472 $user = new User;
473 } else {
474 $user = $wgUser;
475 }
476 }
477 if ( $lang === null ) {
478 global $wgLang;
479 if ( !StubObject::isRealObject( $wgLang ) ) {
480 $wgLang->_unstub();
481 }
482 $lang = $wgLang;
483 }
484 $this->initialiseFromUser( $user, $lang );
485 }
486
487 /**
488 * Get a ParserOptions object from a given user.
489 * Language will be taken from $wgLang.
490 *
491 * @param User $user
492 * @return ParserOptions
493 */
494 public static function newFromUser( $user ) {
495 return new ParserOptions( $user );
496 }
497
498 /**
499 * Get a ParserOptions object from a given user and language
500 *
501 * @param User $user
502 * @param Language $lang
503 * @return ParserOptions
504 */
505 public static function newFromUserAndLang( User $user, Language $lang ) {
506 return new ParserOptions( $user, $lang );
507 }
508
509 /**
510 * Get a ParserOptions object from a IContextSource object
511 *
512 * @param IContextSource $context
513 * @return ParserOptions
514 */
515 public static function newFromContext( IContextSource $context ) {
516 return new ParserOptions( $context->getUser(), $context->getLanguage() );
517 }
518
519 /**
520 * Get user options
521 *
522 * @param User $user
523 * @param Language $lang
524 */
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;
531
532 wfProfileIn( __METHOD__ );
533
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;
549
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;
555
556 wfProfileOut( __METHOD__ );
557 }
558
559 /**
560 * Registers a callback for tracking which ParserOptions which are used.
561 * This is a private API with the parser.
562 * @param callable $callback
563 */
564 function registerWatcher( $callback ) {
565 $this->onAccessCallback = $callback;
566 }
567
568 /**
569 * Called when an option is accessed.
570 * @param string $optionName Name of the option
571 */
572 public function optionUsed( $optionName ) {
573 if ( $this->onAccessCallback ) {
574 call_user_func( $this->onAccessCallback, $optionName );
575 }
576 }
577
578 /**
579 * Returns the full array of options that would have been used by
580 * in 1.16.
581 * Used to get the old parser cache entries when available.
582 * @return array
583 */
584 public static function legacyOptions() {
585 return array(
586 'stubthreshold',
587 'numberheadings',
588 'userlang',
589 'thumbsize',
590 'editsection',
591 'printable'
592 );
593 }
594
595 /**
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.
601 *
602 * Extensions which require it should install 'PageRenderingHash' hook,
603 * which will give them a chance to modify this key based on their own
604 * settings.
605 *
606 * @since 1.17
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
610 */
611 public function optionsHash( $forOptions, $title = null ) {
612 global $wgRenderHashAppend;
613
614 // FIXME: Once the cache key is reorganized this argument
615 // can be dropped. It was used when the math extension was
616 // part of core.
617 $confstr = '*';
618
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;
624 } else {
625 $confstr .= '!*';
626 }
627
628 if ( in_array( 'dateformat', $forOptions ) ) {
629 $confstr .= '!' . $this->getDateFormat();
630 }
631
632 if ( in_array( 'numberheadings', $forOptions ) ) {
633 $confstr .= '!' . ( $this->mNumberHeadings ? '1' : '' );
634 } else {
635 $confstr .= '!*';
636 }
637
638 if ( in_array( 'userlang', $forOptions ) ) {
639 $confstr .= '!' . $this->mUserLang->getCode();
640 } else {
641 $confstr .= '!*';
642 }
643
644 if ( in_array( 'thumbsize', $forOptions ) ) {
645 $confstr .= '!' . $this->mThumbSize;
646 } else {
647 $confstr .= '!*';
648 }
649
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();
654 } else {
655 global $wgContLang;
656 $confstr .= $wgContLang->getExtraHashOptions();
657 }
658
659 $confstr .= $wgRenderHashAppend;
660
661 if ( !in_array( 'editsection', $forOptions ) ) {
662 $confstr .= '!*';
663 } elseif ( !$this->mEditSection ) {
664 $confstr .= '!edit=0';
665 }
666
667 if ( $this->mIsPrintable && in_array( 'printable', $forOptions ) ) {
668 $confstr .= '!printable=1';
669 }
670
671 if ( $this->mExtraKey != '' ) {
672 $confstr .= $this->mExtraKey;
673 }
674
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 ) );
678
679 // Make it a valid memcached key fragment
680 $confstr = str_replace( ' ', '_', $confstr );
681
682 return $confstr;
683 }
684 }