Completed
Branch master (939199)
by
unknown
39:35
created

includes/parser/ParserOptions.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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
use Wikimedia\ScopedCallback;
24
25
/**
26
 * @brief Set options of the Parser
27
 *
28
 * All member variables are supposed to be private in theory, although in
29
 * practice this is not the case.
30
 *
31
 * @ingroup Parser
32
 */
33
class ParserOptions {
34
35
	/**
36
	 * Interlanguage links are removed and returned in an array
37
	 */
38
	private $mInterwikiMagic;
39
40
	/**
41
	 * Allow external images inline?
42
	 */
43
	private $mAllowExternalImages;
44
45
	/**
46
	 * If not, any exception?
47
	 */
48
	private $mAllowExternalImagesFrom;
49
50
	/**
51
	 * If not or it doesn't match, should we check an on-wiki whitelist?
52
	 */
53
	private $mEnableImageWhitelist;
54
55
	/**
56
	 * Date format index
57
	 */
58
	private $mDateFormat = null;
59
60
	/**
61
	 * Create "edit section" links?
62
	 */
63
	private $mEditSection = true;
64
65
	/**
66
	 * Allow inclusion of special pages?
67
	 */
68
	private $mAllowSpecialInclusion;
69
70
	/**
71
	 * Use tidy to cleanup output HTML?
72
	 */
73
	private $mTidy = false;
74
75
	/**
76
	 * Which lang to call for PLURAL and GRAMMAR
77
	 */
78
	private $mInterfaceMessage = false;
79
80
	/**
81
	 * Overrides $mInterfaceMessage with arbitrary language
82
	 */
83
	private $mTargetLanguage = null;
84
85
	/**
86
	 * Maximum size of template expansions, in bytes
87
	 */
88
	private $mMaxIncludeSize;
89
90
	/**
91
	 * Maximum number of nodes touched by PPFrame::expand()
92
	 */
93
	private $mMaxPPNodeCount;
94
95
	/**
96
	 * Maximum number of nodes generated by Preprocessor::preprocessToObj()
97
	 */
98
	private $mMaxGeneratedPPNodeCount;
99
100
	/**
101
	 * Maximum recursion depth in PPFrame::expand()
102
	 */
103
	private $mMaxPPExpandDepth;
104
105
	/**
106
	 * Maximum recursion depth for templates within templates
107
	 */
108
	private $mMaxTemplateDepth;
109
110
	/**
111
	 * Maximum number of calls per parse to expensive parser functions
112
	 */
113
	private $mExpensiveParserFunctionLimit;
114
115
	/**
116
	 * Remove HTML comments. ONLY APPLIES TO PREPROCESS OPERATIONS
117
	 */
118
	private $mRemoveComments = true;
119
120
	/**
121
	 * @var callable Callback for current revision fetching; first argument to call_user_func().
122
	 */
123
	private $mCurrentRevisionCallback =
124
		[ 'Parser', 'statelessFetchRevision' ];
125
126
	/**
127
	 * @var callable Callback for template fetching; first argument to call_user_func().
128
	 */
129
	private $mTemplateCallback =
130
		[ 'Parser', 'statelessFetchTemplate' ];
131
132
	/**
133
	 * @var callable|null Callback to generate a guess for {{REVISIONID}}
134
	 */
135
	private $mSpeculativeRevIdCallback;
136
137
	/**
138
	 * Enable limit report in an HTML comment on output
139
	 */
140
	private $mEnableLimitReport = false;
141
142
	/**
143
	 * Timestamp used for {{CURRENTDAY}} etc.
144
	 */
145
	private $mTimestamp;
146
147
	/**
148
	 * Target attribute for external links
149
	 */
150
	private $mExternalLinkTarget;
151
152
	/**
153
	 * Clean up signature texts?
154
	 * @see Parser::cleanSig
155
	 */
156
	private $mCleanSignatures;
157
158
	/**
159
	 * Transform wiki markup when saving the page?
160
	 */
161
	private $mPreSaveTransform = true;
162
163
	/**
164
	 * Whether content conversion should be disabled
165
	 */
166
	private $mDisableContentConversion;
167
168
	/**
169
	 * Whether title conversion should be disabled
170
	 */
171
	private $mDisableTitleConversion;
172
173
	/**
174
	 * Automatically number headings?
175
	 */
176
	private $mNumberHeadings;
177
178
	/**
179
	 * Thumb size preferred by the user.
180
	 */
181
	private $mThumbSize;
182
183
	/**
184
	 * Maximum article size of an article to be marked as "stub"
185
	 */
186
	private $mStubThreshold;
187
188
	/**
189
	 * Language object of the User language.
190
	 */
191
	private $mUserLang;
192
193
	/**
194
	 * @var User
195
	 * Stored user object
196
	 */
197
	private $mUser;
198
199
	/**
200
	 * Parsing the page for a "preview" operation?
201
	 */
202
	private $mIsPreview = false;
203
204
	/**
205
	 * Parsing the page for a "preview" operation on a single section?
206
	 */
207
	private $mIsSectionPreview = false;
208
209
	/**
210
	 * Parsing the printable version of the page?
211
	 */
212
	private $mIsPrintable = false;
213
214
	/**
215
	 * Extra key that should be present in the caching key.
216
	 */
217
	private $mExtraKey = '';
218
219
	/**
220
	 * Are magic ISBN links enabled?
221
	 */
222
	private $mMagicISBNLinks = true;
223
224
	/**
225
	 * Are magic PMID links enabled?
226
	 */
227
	private $mMagicPMIDLinks = true;
228
229
	/**
230
	 * Are magic RFC links enabled?
231
	 */
232
	private $mMagicRFCLinks = true;
233
234
	/**
235
	 * Function to be called when an option is accessed.
236
	 */
237
	private $onAccessCallback = null;
238
239
	/**
240
	 * If the page being parsed is a redirect, this should hold the redirect
241
	 * target.
242
	 * @var Title|null
243
	 */
244
	private $redirectTarget = null;
245
246
	public function getInterwikiMagic() {
247
		return $this->mInterwikiMagic;
248
	}
249
250
	public function getAllowExternalImages() {
251
		return $this->mAllowExternalImages;
252
	}
253
254
	public function getAllowExternalImagesFrom() {
255
		return $this->mAllowExternalImagesFrom;
256
	}
257
258
	public function getEnableImageWhitelist() {
259
		return $this->mEnableImageWhitelist;
260
	}
261
262
	public function getEditSection() {
263
		return $this->mEditSection;
264
	}
265
266
	public function getNumberHeadings() {
267
		$this->optionUsed( 'numberheadings' );
268
269
		return $this->mNumberHeadings;
270
	}
271
272
	public function getAllowSpecialInclusion() {
273
		return $this->mAllowSpecialInclusion;
274
	}
275
276
	public function getTidy() {
277
		return $this->mTidy;
278
	}
279
280
	public function getInterfaceMessage() {
281
		return $this->mInterfaceMessage;
282
	}
283
284
	public function getTargetLanguage() {
285
		return $this->mTargetLanguage;
286
	}
287
288
	public function getMaxIncludeSize() {
289
		return $this->mMaxIncludeSize;
290
	}
291
292
	public function getMaxPPNodeCount() {
293
		return $this->mMaxPPNodeCount;
294
	}
295
296
	public function getMaxGeneratedPPNodeCount() {
297
		return $this->mMaxGeneratedPPNodeCount;
298
	}
299
300
	public function getMaxPPExpandDepth() {
301
		return $this->mMaxPPExpandDepth;
302
	}
303
304
	public function getMaxTemplateDepth() {
305
		return $this->mMaxTemplateDepth;
306
	}
307
308
	/* @since 1.20 */
309
	public function getExpensiveParserFunctionLimit() {
310
		return $this->mExpensiveParserFunctionLimit;
311
	}
312
313
	public function getRemoveComments() {
314
		return $this->mRemoveComments;
315
	}
316
317
	/* @since 1.24 */
318
	public function getCurrentRevisionCallback() {
319
		return $this->mCurrentRevisionCallback;
320
	}
321
322
	public function getTemplateCallback() {
323
		return $this->mTemplateCallback;
324
	}
325
326
	/** @since 1.28 */
327
	public function getSpeculativeRevIdCallback() {
328
		return $this->mSpeculativeRevIdCallback;
329
	}
330
331
	public function getEnableLimitReport() {
332
		return $this->mEnableLimitReport;
333
	}
334
335
	public function getCleanSignatures() {
336
		return $this->mCleanSignatures;
337
	}
338
339
	public function getExternalLinkTarget() {
340
		return $this->mExternalLinkTarget;
341
	}
342
343
	public function getDisableContentConversion() {
344
		return $this->mDisableContentConversion;
345
	}
346
347
	public function getDisableTitleConversion() {
348
		return $this->mDisableTitleConversion;
349
	}
350
351
	public function getThumbSize() {
352
		$this->optionUsed( 'thumbsize' );
353
354
		return $this->mThumbSize;
355
	}
356
357
	public function getStubThreshold() {
358
		$this->optionUsed( 'stubthreshold' );
359
360
		return $this->mStubThreshold;
361
	}
362
363
	public function getIsPreview() {
364
		return $this->mIsPreview;
365
	}
366
367
	public function getIsSectionPreview() {
368
		return $this->mIsSectionPreview;
369
	}
370
371
	public function getIsPrintable() {
372
		$this->optionUsed( 'printable' );
373
374
		return $this->mIsPrintable;
375
	}
376
377
	public function getUser() {
378
		return $this->mUser;
379
	}
380
381
	public function getPreSaveTransform() {
382
		return $this->mPreSaveTransform;
383
	}
384
385
	public function getDateFormat() {
386
		$this->optionUsed( 'dateformat' );
387
		if ( !isset( $this->mDateFormat ) ) {
388
			$this->mDateFormat = $this->mUser->getDatePreference();
389
		}
390
		return $this->mDateFormat;
391
	}
392
393
	public function getTimestamp() {
394
		if ( !isset( $this->mTimestamp ) ) {
395
			$this->mTimestamp = wfTimestampNow();
396
		}
397
		return $this->mTimestamp;
398
	}
399
400
	/**
401
	 * Get the user language used by the parser for this page and split the parser cache.
402
	 *
403
	 * @warning: Calling this causes the parser cache to be fragmented by user language!
404
	 * To avoid cache fragmentation, output should not depend on the user language.
405
	 * Use Parser::getFunctionLang() or Parser::getTargetLanguage() instead!
406
	 *
407
	 * @note This function will trigger a cache fragmentation by recording the
408
	 * 'userlang' option, see optionUsed(). This is done to avoid cache pollution
409
	 * when the page is rendered based on the language of the user.
410
	 *
411
	 * @note When saving, this will return the default language instead of the user's.
412
	 * {{int: }} uses this which used to produce inconsistent link tables (bug 14404).
413
	 *
414
	 * @return Language
415
	 * @since 1.19
416
	 */
417
	public function getUserLangObj() {
418
		$this->optionUsed( 'userlang' );
419
		return $this->mUserLang;
420
	}
421
422
	/**
423
	 * Same as getUserLangObj() but returns a string instead.
424
	 *
425
	 * @warning: Calling this causes the parser cache to be fragmented by user language!
426
	 * To avoid cache fragmentation, output should not depend on the user language.
427
	 * Use Parser::getFunctionLang() or Parser::getTargetLanguage() instead!
428
	 *
429
	 * @see getUserLangObj()
430
	 *
431
	 * @return string Language code
432
	 * @since 1.17
433
	 */
434
	public function getUserLang() {
435
		return $this->getUserLangObj()->getCode();
436
	}
437
438
	/**
439
	 * @since 1.28
440
	 * @return bool
441
	 */
442
	public function getMagicISBNLinks() {
443
		return $this->mMagicISBNLinks;
444
	}
445
446
	/**
447
	 * @since 1.28
448
	 * @return bool
449
	 */
450
	public function getMagicPMIDLinks() {
451
		return $this->mMagicPMIDLinks;
452
	}
453
	/**
454
	 * @since 1.28
455
	 * @return bool
456
	 */
457
	public function getMagicRFCLinks() {
458
		return $this->mMagicRFCLinks;
459
	}
460
	public function setInterwikiMagic( $x ) {
461
		return wfSetVar( $this->mInterwikiMagic, $x );
462
	}
463
464
	public function setAllowExternalImages( $x ) {
465
		return wfSetVar( $this->mAllowExternalImages, $x );
466
	}
467
468
	public function setAllowExternalImagesFrom( $x ) {
469
		return wfSetVar( $this->mAllowExternalImagesFrom, $x );
470
	}
471
472
	public function setEnableImageWhitelist( $x ) {
473
		return wfSetVar( $this->mEnableImageWhitelist, $x );
474
	}
475
476
	public function setDateFormat( $x ) {
477
		return wfSetVar( $this->mDateFormat, $x );
478
	}
479
480
	public function setEditSection( $x ) {
481
		return wfSetVar( $this->mEditSection, $x );
482
	}
483
484
	public function setNumberHeadings( $x ) {
485
		return wfSetVar( $this->mNumberHeadings, $x );
486
	}
487
488
	public function setAllowSpecialInclusion( $x ) {
489
		return wfSetVar( $this->mAllowSpecialInclusion, $x );
490
	}
491
492
	public function setTidy( $x ) {
493
		return wfSetVar( $this->mTidy, $x );
494
	}
495
496
	public function setInterfaceMessage( $x ) {
497
		return wfSetVar( $this->mInterfaceMessage, $x );
498
	}
499
500
	public function setTargetLanguage( $x ) {
501
		return wfSetVar( $this->mTargetLanguage, $x, true );
502
	}
503
504
	public function setMaxIncludeSize( $x ) {
505
		return wfSetVar( $this->mMaxIncludeSize, $x );
506
	}
507
508
	public function setMaxPPNodeCount( $x ) {
509
		return wfSetVar( $this->mMaxPPNodeCount, $x );
510
	}
511
512
	public function setMaxGeneratedPPNodeCount( $x ) {
513
		return wfSetVar( $this->mMaxGeneratedPPNodeCount, $x );
514
	}
515
516
	public function setMaxTemplateDepth( $x ) {
517
		return wfSetVar( $this->mMaxTemplateDepth, $x );
518
	}
519
520
	/* @since 1.20 */
521
	public function setExpensiveParserFunctionLimit( $x ) {
522
		return wfSetVar( $this->mExpensiveParserFunctionLimit, $x );
523
	}
524
525
	public function setRemoveComments( $x ) {
526
		return wfSetVar( $this->mRemoveComments, $x );
527
	}
528
529
	/* @since 1.24 */
530
	public function setCurrentRevisionCallback( $x ) {
531
		return wfSetVar( $this->mCurrentRevisionCallback, $x );
532
	}
533
534
	/** @since 1.28 */
535
	public function setSpeculativeRevIdCallback( $x ) {
536
		return wfSetVar( $this->mSpeculativeRevIdCallback, $x );
537
	}
538
539
	public function setTemplateCallback( $x ) {
540
		return wfSetVar( $this->mTemplateCallback, $x );
541
	}
542
543
	public function enableLimitReport( $x = true ) {
544
		return wfSetVar( $this->mEnableLimitReport, $x );
545
	}
546
547
	public function setTimestamp( $x ) {
548
		return wfSetVar( $this->mTimestamp, $x );
549
	}
550
551
	public function setCleanSignatures( $x ) {
552
		return wfSetVar( $this->mCleanSignatures, $x );
553
	}
554
555
	public function setExternalLinkTarget( $x ) {
556
		return wfSetVar( $this->mExternalLinkTarget, $x );
557
	}
558
559
	public function disableContentConversion( $x = true ) {
560
		return wfSetVar( $this->mDisableContentConversion, $x );
561
	}
562
563
	public function disableTitleConversion( $x = true ) {
564
		return wfSetVar( $this->mDisableTitleConversion, $x );
565
	}
566
567
	public function setUserLang( $x ) {
568
		if ( is_string( $x ) ) {
569
			$x = Language::factory( $x );
570
		}
571
572
		return wfSetVar( $this->mUserLang, $x );
573
	}
574
575
	public function setThumbSize( $x ) {
576
		return wfSetVar( $this->mThumbSize, $x );
577
	}
578
579
	public function setStubThreshold( $x ) {
580
		return wfSetVar( $this->mStubThreshold, $x );
581
	}
582
583
	public function setPreSaveTransform( $x ) {
584
		return wfSetVar( $this->mPreSaveTransform, $x );
585
	}
586
587
	public function setIsPreview( $x ) {
588
		return wfSetVar( $this->mIsPreview, $x );
589
	}
590
591
	public function setIsSectionPreview( $x ) {
592
		return wfSetVar( $this->mIsSectionPreview, $x );
593
	}
594
595
	public function setIsPrintable( $x ) {
596
		return wfSetVar( $this->mIsPrintable, $x );
597
	}
598
599
	/**
600
	 * Set the redirect target.
601
	 *
602
	 * Note that setting or changing this does not *make* the page a redirect
603
	 * or change its target, it merely records the information for reference
604
	 * during the parse.
605
	 *
606
	 * @since 1.24
607
	 * @param Title|null $title
608
	 */
609
	function setRedirectTarget( $title ) {
610
		$this->redirectTarget = $title;
611
	}
612
613
	/**
614
	 * Get the previously-set redirect target.
615
	 *
616
	 * @since 1.24
617
	 * @return Title|null
618
	 */
619
	function getRedirectTarget() {
620
		return $this->redirectTarget;
621
	}
622
623
	/**
624
	 * Extra key that should be present in the parser cache key.
625
	 * @param string $key
626
	 */
627
	public function addExtraKey( $key ) {
628
		$this->mExtraKey .= '!' . $key;
629
	}
630
631
	/**
632
	 * Constructor
633
	 * @param User $user
634
	 * @param Language $lang
635
	 */
636
	public function __construct( $user = null, $lang = null ) {
637
		if ( $user === null ) {
638
			global $wgUser;
639
			if ( $wgUser === null ) {
640
				$user = new User;
641
			} else {
642
				$user = $wgUser;
643
			}
644
		}
645
		if ( $lang === null ) {
646
			global $wgLang;
647
			if ( !StubObject::isRealObject( $wgLang ) ) {
648
				$wgLang->_unstub();
649
			}
650
			$lang = $wgLang;
651
		}
652
		$this->initialiseFromUser( $user, $lang );
653
	}
654
655
	/**
656
	 * Get a ParserOptions object for an anonymous user
657
	 * @since 1.27
658
	 * @return ParserOptions
659
	 */
660
	public static function newFromAnon() {
661
		global $wgContLang;
662
		return new ParserOptions( new User, $wgContLang );
663
	}
664
665
	/**
666
	 * Get a ParserOptions object from a given user.
667
	 * Language will be taken from $wgLang.
668
	 *
669
	 * @param User $user
670
	 * @return ParserOptions
671
	 */
672
	public static function newFromUser( $user ) {
673
		return new ParserOptions( $user );
674
	}
675
676
	/**
677
	 * Get a ParserOptions object from a given user and language
678
	 *
679
	 * @param User $user
680
	 * @param Language $lang
681
	 * @return ParserOptions
682
	 */
683
	public static function newFromUserAndLang( User $user, Language $lang ) {
684
		return new ParserOptions( $user, $lang );
685
	}
686
687
	/**
688
	 * Get a ParserOptions object from a IContextSource object
689
	 *
690
	 * @param IContextSource $context
691
	 * @return ParserOptions
692
	 */
693
	public static function newFromContext( IContextSource $context ) {
694
		return new ParserOptions( $context->getUser(), $context->getLanguage() );
695
	}
696
697
	/**
698
	 * Get user options
699
	 *
700
	 * @param User $user
701
	 * @param Language $lang
702
	 */
703
	private function initialiseFromUser( $user, $lang ) {
704
		global $wgInterwikiMagic, $wgAllowExternalImages,
705
			$wgAllowExternalImagesFrom, $wgEnableImageWhitelist, $wgAllowSpecialInclusion,
706
			$wgMaxArticleSize, $wgMaxPPNodeCount, $wgMaxTemplateDepth, $wgMaxPPExpandDepth,
707
			$wgCleanSignatures, $wgExternalLinkTarget, $wgExpensiveParserFunctionLimit,
708
			$wgMaxGeneratedPPNodeCount, $wgDisableLangConversion, $wgDisableTitleConversion,
709
			$wgEnableMagicLinks;
710
711
		// *UPDATE* ParserOptions::matches() if any of this changes as needed
712
		$this->mInterwikiMagic = $wgInterwikiMagic;
713
		$this->mAllowExternalImages = $wgAllowExternalImages;
714
		$this->mAllowExternalImagesFrom = $wgAllowExternalImagesFrom;
715
		$this->mEnableImageWhitelist = $wgEnableImageWhitelist;
716
		$this->mAllowSpecialInclusion = $wgAllowSpecialInclusion;
717
		$this->mMaxIncludeSize = $wgMaxArticleSize * 1024;
718
		$this->mMaxPPNodeCount = $wgMaxPPNodeCount;
719
		$this->mMaxGeneratedPPNodeCount = $wgMaxGeneratedPPNodeCount;
720
		$this->mMaxPPExpandDepth = $wgMaxPPExpandDepth;
721
		$this->mMaxTemplateDepth = $wgMaxTemplateDepth;
722
		$this->mExpensiveParserFunctionLimit = $wgExpensiveParserFunctionLimit;
723
		$this->mCleanSignatures = $wgCleanSignatures;
724
		$this->mExternalLinkTarget = $wgExternalLinkTarget;
725
		$this->mDisableContentConversion = $wgDisableLangConversion;
726
		$this->mDisableTitleConversion = $wgDisableLangConversion || $wgDisableTitleConversion;
727
		$this->mMagicISBNLinks = $wgEnableMagicLinks['ISBN'];
728
		$this->mMagicPMIDLinks = $wgEnableMagicLinks['PMID'];
729
		$this->mMagicRFCLinks = $wgEnableMagicLinks['RFC'];
730
731
		$this->mUser = $user;
732
		$this->mNumberHeadings = $user->getOption( 'numberheadings' );
733
		$this->mThumbSize = $user->getOption( 'thumbsize' );
734
		$this->mStubThreshold = $user->getStubThreshold();
735
		$this->mUserLang = $lang;
736
737
	}
738
739
	/**
740
	 * Check if these options match that of another options set
741
	 *
742
	 * This ignores report limit settings that only affect HTML comments
743
	 *
744
	 * @param ParserOptions $other
745
	 * @return bool
746
	 * @since 1.25
747
	 */
748
	public function matches( ParserOptions $other ) {
749
		$fields = array_keys( get_class_vars( __CLASS__ ) );
750
		$fields = array_diff( $fields, [
751
			'mEnableLimitReport', // only effects HTML comments
752
			'onAccessCallback', // only used for ParserOutput option tracking
753
		] );
754
		foreach ( $fields as $field ) {
755
			if ( !is_object( $this->$field ) && $this->$field !== $other->$field ) {
756
				return false;
757
			}
758
		}
759
		// Check the object and lazy-loaded options
760
		return (
761
			$this->mUserLang->equals( $other->mUserLang ) &&
762
			$this->getDateFormat() === $other->getDateFormat()
763
		);
764
	}
765
766
	/**
767
	 * Registers a callback for tracking which ParserOptions which are used.
768
	 * This is a private API with the parser.
769
	 * @param callable $callback
770
	 */
771
	public function registerWatcher( $callback ) {
772
		$this->onAccessCallback = $callback;
773
	}
774
775
	/**
776
	 * Called when an option is accessed.
777
	 * Calls the watcher that was set using registerWatcher().
778
	 * Typically, the watcher callback is ParserOutput::registerOption().
779
	 * The information registered that way will be used by ParserCache::save().
780
	 *
781
	 * @param string $optionName Name of the option
782
	 */
783
	public function optionUsed( $optionName ) {
784
		if ( $this->onAccessCallback ) {
785
			call_user_func( $this->onAccessCallback, $optionName );
786
		}
787
	}
788
789
	/**
790
	 * Returns the full array of options that would have been used by
791
	 * in 1.16.
792
	 * Used to get the old parser cache entries when available.
793
	 * @return array
794
	 */
795
	public static function legacyOptions() {
796
		return [
797
			'stubthreshold',
798
			'numberheadings',
799
			'userlang',
800
			'thumbsize',
801
			'editsection',
802
			'printable'
803
		];
804
	}
805
806
	/**
807
	 * Generate a hash string with the values set on these ParserOptions
808
	 * for the keys given in the array.
809
	 * This will be used as part of the hash key for the parser cache,
810
	 * so users sharing the options with vary for the same page share
811
	 * the same cached data safely.
812
	 *
813
	 * Extensions which require it should install 'PageRenderingHash' hook,
814
	 * which will give them a chance to modify this key based on their own
815
	 * settings.
816
	 *
817
	 * @since 1.17
818
	 * @param array $forOptions
819
	 * @param Title $title Used to get the content language of the page (since r97636)
820
	 * @return string Page rendering hash
821
	 */
822
	public function optionsHash( $forOptions, $title = null ) {
823
		global $wgRenderHashAppend;
824
825
		// FIXME: Once the cache key is reorganized this argument
826
		// can be dropped. It was used when the math extension was
827
		// part of core.
828
		$confstr = '*';
829
830
		// Space assigned for the stubthreshold but unused
831
		// since it disables the parser cache, its value will always
832
		// be 0 when this function is called by parsercache.
833
		if ( in_array( 'stubthreshold', $forOptions ) ) {
834
			$confstr .= '!' . $this->mStubThreshold;
835
		} else {
836
			$confstr .= '!*';
837
		}
838
839
		if ( in_array( 'dateformat', $forOptions ) ) {
840
			$confstr .= '!' . $this->getDateFormat();
841
		}
842
843
		if ( in_array( 'numberheadings', $forOptions ) ) {
844
			$confstr .= '!' . ( $this->mNumberHeadings ? '1' : '' );
845
		} else {
846
			$confstr .= '!*';
847
		}
848
849
		if ( in_array( 'userlang', $forOptions ) ) {
850
			$confstr .= '!' . $this->mUserLang->getCode();
851
		} else {
852
			$confstr .= '!*';
853
		}
854
855
		if ( in_array( 'thumbsize', $forOptions ) ) {
856
			$confstr .= '!' . $this->mThumbSize;
857
		} else {
858
			$confstr .= '!*';
859
		}
860
861
		// add in language specific options, if any
862
		// @todo FIXME: This is just a way of retrieving the url/user preferred variant
863
		if ( !is_null( $title ) ) {
864
			$confstr .= $title->getPageLanguage()->getExtraHashOptions();
865
		} else {
866
			global $wgContLang;
867
			$confstr .= $wgContLang->getExtraHashOptions();
868
		}
869
870
		$confstr .= $wgRenderHashAppend;
871
872
		// @note: as of Feb 2015, core never sets the editsection flag, since it uses
873
		// <mw:editsection> tags to inject editsections on the fly. However, extensions
874
		// may be using it by calling ParserOption::optionUsed resp. ParserOutput::registerOption
875
		// directly. At least Wikibase does at this point in time.
876
		if ( !in_array( 'editsection', $forOptions ) ) {
877
			$confstr .= '!*';
878
		} elseif ( !$this->mEditSection ) {
879
			$confstr .= '!edit=0';
880
		}
881
882
		if ( $this->mIsPrintable && in_array( 'printable', $forOptions ) ) {
883
			$confstr .= '!printable=1';
884
		}
885
886
		if ( $this->mExtraKey != '' ) {
887
			$confstr .= $this->mExtraKey;
888
		}
889
890
		// Give a chance for extensions to modify the hash, if they have
891
		// extra options or other effects on the parser cache.
892
		Hooks::run( 'PageRenderingHash', [ &$confstr, $this->getUser(), &$forOptions ] );
893
894
		// Make it a valid memcached key fragment
895
		$confstr = str_replace( ' ', '_', $confstr );
896
897
		return $confstr;
898
	}
899
900
	/**
901
	 * Sets a hook to force that a page exists, and sets a current revision callback to return
902
	 * a revision with custom content when the current revision of the page is requested.
903
	 *
904
	 * @since 1.25
905
	 * @param Title $title
906
	 * @param Content $content
907
	 * @param User $user The user that the fake revision is attributed to
908
	 * @return ScopedCallback to unset the hook
909
	 */
910
	public function setupFakeRevision( $title, $content, $user ) {
911
		$oldCallback = $this->setCurrentRevisionCallback(
0 ignored issues
show
$oldCallback is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
912
			function (
913
				$titleToCheck, $parser = false ) use ( $title, $content, $user, &$oldCallback
914
			) {
915
				if ( $titleToCheck->equals( $title ) ) {
916
					return new Revision( [
917
						'page' => $title->getArticleID(),
918
						'user_text' => $user->getName(),
919
						'user' => $user->getId(),
920
						'parent_id' => $title->getLatestRevID(),
921
						'title' => $title,
922
						'content' => $content
923
					] );
924
				} else {
925
					return call_user_func( $oldCallback, $titleToCheck, $parser );
926
				}
927
			}
928
		);
929
930
		global $wgHooks;
931
		$wgHooks['TitleExists'][] =
932
			function ( $titleToCheck, &$exists ) use ( $title ) {
933
				if ( $titleToCheck->equals( $title ) ) {
934
					$exists = true;
935
				}
936
			};
937
		end( $wgHooks['TitleExists'] );
938
		$key = key( $wgHooks['TitleExists'] );
939
		LinkCache::singleton()->clearBadLink( $title->getPrefixedDBkey() );
940
		return new ScopedCallback( function () use ( $title, $key ) {
941
			global $wgHooks;
942
			unset( $wgHooks['TitleExists'][$key] );
943
			LinkCache::singleton()->clearLink( $title );
944
		} );
945
	}
946
}
947