MediaWiki  master
ParserOptions.php
Go to the documentation of this file.
1 <?php
27 use Wikimedia\ScopedCallback;
28 
45 
51  private static $defaults = null;
52 
57  private static $lazyOptions = [
58  'dateformat' => [ __CLASS__, 'initDateFormat' ],
59  'speculativeRevId' => [ __CLASS__, 'initSpeculativeRevId' ],
60  'speculativePageId' => [ __CLASS__, 'initSpeculativePageId' ],
61  ];
62 
67  private static $inCacheKey = [
68  'dateformat' => true,
69  'numberheadings' => true,
70  'thumbsize' => true,
71  'stubthreshold' => true,
72  'printable' => true,
73  'userlang' => true,
74  ];
75 
80  private $options;
81 
87  private $mTimestamp;
88 
94  private $mUser;
95 
101  private $onAccessCallback = null;
102 
109  private $redirectTarget = null;
110 
114  private $mExtraKey = '';
115 
122  public function getOption( $name ) {
123  if ( !array_key_exists( $name, $this->options ) ) {
124  throw new InvalidArgumentException( "Unknown parser option $name" );
125  }
126 
127  $this->lazyLoadOption( $name );
128  if ( !empty( self::$inCacheKey[$name] ) ) {
129  $this->optionUsed( $name );
130  }
131  return $this->options[$name];
132  }
133 
137  private function lazyLoadOption( $name ) {
138  if ( isset( self::$lazyOptions[$name] ) && $this->options[$name] === null ) {
139  $this->options[$name] = call_user_func( self::$lazyOptions[$name], $this, $name );
140  }
141  }
142 
151  public function setOption( $name, $value ) {
152  if ( !array_key_exists( $name, $this->options ) ) {
153  throw new InvalidArgumentException( "Unknown parser option $name" );
154  }
155  $old = $this->options[$name];
156  $this->options[$name] = $value;
157  return $old;
158  }
159 
168  protected function setOptionLegacy( $name, $value ) {
169  if ( !array_key_exists( $name, $this->options ) ) {
170  throw new InvalidArgumentException( "Unknown parser option $name" );
171  }
172  return wfSetVar( $this->options[$name], $value );
173  }
174 
183  public function getInterwikiMagic() {
184  return $this->getOption( 'interwikiMagic' );
185  }
186 
192  public function setInterwikiMagic( $x ) {
193  return $this->setOptionLegacy( 'interwikiMagic', $x );
194  }
195 
200  public function getAllowExternalImages() {
201  return $this->getOption( 'allowExternalImages' );
202  }
203 
211  public function setAllowExternalImages( $x ) {
212  wfDeprecated( __METHOD__, '1.35' );
213  return $this->setOptionLegacy( 'allowExternalImages', $x );
214  }
215 
223  public function getAllowExternalImagesFrom() {
224  return $this->getOption( 'allowExternalImagesFrom' );
225  }
226 
237  public function setAllowExternalImagesFrom( $x ) {
238  wfDeprecated( __METHOD__, '1.35' );
239  return $this->setOptionLegacy( 'allowExternalImagesFrom', $x );
240  }
241 
246  public function getEnableImageWhitelist() {
247  return $this->getOption( 'enableImageWhitelist' );
248  }
249 
257  public function setEnableImageWhitelist( $x ) {
258  wfDeprecated( __METHOD__, '1.35' );
259  return $this->setOptionLegacy( 'enableImageWhitelist', $x );
260  }
261 
266  public function getNumberHeadings() {
267  return $this->getOption( 'numberheadings' );
268  }
269 
275  public function setNumberHeadings( $x ) {
276  return $this->setOptionLegacy( 'numberheadings', $x );
277  }
278 
283  public function getAllowSpecialInclusion() {
284  return $this->getOption( 'allowSpecialInclusion' );
285  }
286 
292  public function setAllowSpecialInclusion( $x ) {
293  return $this->setOptionLegacy( 'allowSpecialInclusion', $x );
294  }
295 
301  public function getTidy() {
302  wfDeprecated( __METHOD__, '1.35' );
303  return $this->getOption( 'tidy' );
304  }
305 
312  public function setTidy( $x ) {
313  if ( !$x ) {
314  wfDeprecatedMsg( 'Disabling tidy is deprecated since MediaWiki 1.33', '1.33' );
315  }
316  return $this->setOptionLegacy( 'tidy', $x );
317  }
318 
323  public function getInterfaceMessage() {
324  return $this->getOption( 'interfaceMessage' );
325  }
326 
332  public function setInterfaceMessage( $x ) {
333  return $this->setOptionLegacy( 'interfaceMessage', $x );
334  }
335 
340  public function getTargetLanguage() {
341  return $this->getOption( 'targetLanguage' );
342  }
343 
349  public function setTargetLanguage( $x ) {
350  return $this->setOption( 'targetLanguage', $x );
351  }
352 
357  public function getMaxIncludeSize() {
358  return $this->getOption( 'maxIncludeSize' );
359  }
360 
366  public function setMaxIncludeSize( $x ) {
367  return $this->setOptionLegacy( 'maxIncludeSize', $x );
368  }
369 
374  public function getMaxPPNodeCount() {
375  return $this->getOption( 'maxPPNodeCount' );
376  }
377 
383  public function setMaxPPNodeCount( $x ) {
384  return $this->setOptionLegacy( 'maxPPNodeCount', $x );
385  }
386 
391  public function getMaxPPExpandDepth() {
392  return $this->getOption( 'maxPPExpandDepth' );
393  }
394 
399  public function getMaxTemplateDepth() {
400  return $this->getOption( 'maxTemplateDepth' );
401  }
402 
408  public function setMaxTemplateDepth( $x ) {
409  return $this->setOptionLegacy( 'maxTemplateDepth', $x );
410  }
411 
418  return $this->getOption( 'expensiveParserFunctionLimit' );
419  }
420 
427  public function setExpensiveParserFunctionLimit( $x ) {
428  return $this->setOptionLegacy( 'expensiveParserFunctionLimit', $x );
429  }
430 
436  public function getRemoveComments() {
437  return $this->getOption( 'removeComments' );
438  }
439 
446  public function setRemoveComments( $x ) {
447  return $this->setOptionLegacy( 'removeComments', $x );
448  }
449 
454  public function getEnableLimitReport() {
455  return $this->getOption( 'enableLimitReport' );
456  }
457 
463  public function enableLimitReport( $x = true ) {
464  return $this->setOptionLegacy( 'enableLimitReport', $x );
465  }
466 
472  public function getCleanSignatures() {
473  return $this->getOption( 'cleanSignatures' );
474  }
475 
482  public function setCleanSignatures( $x ) {
483  return $this->setOptionLegacy( 'cleanSignatures', $x );
484  }
485 
490  public function getExternalLinkTarget() {
491  return $this->getOption( 'externalLinkTarget' );
492  }
493 
499  public function setExternalLinkTarget( $x ) {
500  return $this->setOptionLegacy( 'externalLinkTarget', $x );
501  }
502 
507  public function getDisableContentConversion() {
508  return $this->getOption( 'disableContentConversion' );
509  }
510 
516  public function disableContentConversion( $x = true ) {
517  return $this->setOptionLegacy( 'disableContentConversion', $x );
518  }
519 
524  public function getDisableTitleConversion() {
525  return $this->getOption( 'disableTitleConversion' );
526  }
527 
533  public function disableTitleConversion( $x = true ) {
534  return $this->setOptionLegacy( 'disableTitleConversion', $x );
535  }
536 
541  public function getThumbSize() {
542  return $this->getOption( 'thumbsize' );
543  }
544 
550  public function setThumbSize( $x ) {
551  return $this->setOptionLegacy( 'thumbsize', $x );
552  }
553 
558  public function getStubThreshold() {
559  return $this->getOption( 'stubthreshold' );
560  }
561 
567  public function setStubThreshold( $x ) {
568  return $this->setOptionLegacy( 'stubthreshold', $x );
569  }
570 
575  public function getIsPreview() {
576  return $this->getOption( 'isPreview' );
577  }
578 
584  public function setIsPreview( $x ) {
585  return $this->setOptionLegacy( 'isPreview', $x );
586  }
587 
592  public function getIsSectionPreview() {
593  return $this->getOption( 'isSectionPreview' );
594  }
595 
601  public function setIsSectionPreview( $x ) {
602  return $this->setOptionLegacy( 'isSectionPreview', $x );
603  }
604 
609  public function getIsPrintable() {
610  return $this->getOption( 'printable' );
611  }
612 
618  public function setIsPrintable( $x ) {
619  return $this->setOptionLegacy( 'printable', $x );
620  }
621 
626  public function getPreSaveTransform() {
627  return $this->getOption( 'preSaveTransform' );
628  }
629 
635  public function setPreSaveTransform( $x ) {
636  return $this->setOptionLegacy( 'preSaveTransform', $x );
637  }
638 
643  public function getDateFormat() {
644  return $this->getOption( 'dateformat' );
645  }
646 
652  private static function initDateFormat( ParserOptions $popt ) {
653  return $popt->mUser->getDatePreference();
654  }
655 
661  public function setDateFormat( $x ) {
662  return $this->setOptionLegacy( 'dateformat', $x );
663  }
664 
682  public function getUserLangObj() {
683  return $this->getOption( 'userlang' );
684  }
685 
698  public function getUserLang() {
699  return $this->getUserLangObj()->getCode();
700  }
701 
707  public function setUserLang( $x ) {
708  if ( is_string( $x ) ) {
709  $x = MediaWikiServices::getInstance()->getLanguageFactory()->getLanguage( $x );
710  }
711 
712  return $this->setOptionLegacy( 'userlang', $x );
713  }
714 
720  public function getMagicISBNLinks() {
721  return $this->getOption( 'magicISBNLinks' );
722  }
723 
729  public function getMagicPMIDLinks() {
730  return $this->getOption( 'magicPMIDLinks' );
731  }
732 
738  public function getMagicRFCLinks() {
739  return $this->getOption( 'magicRFCLinks' );
740  }
741 
756  public function getAllowUnsafeRawHtml() {
757  return $this->getOption( 'allowUnsafeRawHtml' );
758  }
759 
768  public function setAllowUnsafeRawHtml( $x ) {
769  return $this->setOptionLegacy( 'allowUnsafeRawHtml', $x );
770  }
771 
777  public function getWrapOutputClass() {
778  return $this->getOption( 'wrapclass' );
779  }
780 
788  public function setWrapOutputClass( $className ) {
789  if ( $className === true ) { // DWIM, they probably want the default class name
790  $className = 'mw-parser-output';
791  }
792  if ( $className === false ) {
793  wfDeprecated( __METHOD__ . '( false )', '1.31' );
794  }
795  return $this->setOption( 'wrapclass', $className );
796  }
797 
804  public function getCurrentRevisionCallback() {
805  wfDeprecated( __METHOD__, '1.35' );
806  $revCb = $this->getOption( 'currentRevisionCallback' );
807 
808  // As a temporary measure, while both currentRevisionCallback and
809  // currentRevisionRecordCallback are supported, retrieving one that is
810  // not set first checks if the other is set, so that the end result works
811  // regardless of which setter was used, since one extension may set a
812  // RevisionCallback and another may ask for the RevisionRecordCallback
813  if ( $revCb === [ Parser::class, 'statelessFetchRevision' ] ) {
814  // currentRevisionCallback is set to the default, check if
815  // currentRevisionRecordCallback is set (and not the default)
816  $revRecordCb = $this->getOption( 'currentRevisionRecordCallback' );
817  if ( $revRecordCb !== [ Parser::class, 'statelessFetchRevisionRecord' ] ) {
818  // currentRevisionRecordCallback is set and not the default,
819  // convert it
820  $revCb = function ( Title $title, $parser = false ) use ( $revRecordCb ) {
821  $revRecord = call_user_func(
822  $revRecordCb,
823  $title,
824  $parser ?: null
825  );
826  if ( $revRecord ) {
827  return new Revision( $revRecord );
828  }
829  return false;
830  };
831  }
832  }
833  return $revCb;
834  }
835 
843  $revRecordCb = $this->getOption( 'currentRevisionRecordCallback' );
844 
845  // See explanation above
846  if ( $revRecordCb === [ Parser::class, 'statelessFetchRevisionRecord' ] ) {
847  // currentRevisionRecordCallback is set to the default, check if
848  // currentRevisionCallback is set (and not the default)
849  $revCb = $this->getOption( 'currentRevisionCallback' );
850  if ( $revCb !== [ Parser::class, 'statelessFetchRevision' ] ) {
851  // currentRevisionCallback is set and not the default, convert it
852  $revRecordCb = function ( Title $title, $parser = null ) use ( $revCb ) {
853  $rev = call_user_func( $revCb, $title, $parser ?? false );
854  if ( $rev ) {
855  return $rev->getRevisionRecord();
856  }
857  return false;
858  };
859  }
860  }
861  return $revRecordCb;
862  }
863 
871  public function setCurrentRevisionCallback( $x ) {
872  wfDeprecated( __METHOD__, '1.35' );
873  return $this->setOptionLegacy( 'currentRevisionCallback', $x );
874  }
875 
883  public function setCurrentRevisionRecordCallback( $x ) {
884  return $this->setOption( 'currentRevisionRecordCallback', $x );
885  }
886 
891  public function getTemplateCallback() {
892  return $this->getOption( 'templateCallback' );
893  }
894 
900  public function setTemplateCallback( $x ) {
901  return $this->setOptionLegacy( 'templateCallback', $x );
902  }
903 
914  public function getSpeculativeRevId() {
915  return $this->getOption( 'speculativeRevId' );
916  }
917 
928  public function getSpeculativePageId() {
929  return $this->getOption( 'speculativePageId' );
930  }
931 
938  private static function initSpeculativeRevId( ParserOptions $popt ) {
939  $cb = $popt->getOption( 'speculativeRevIdCallback' );
940  $id = $cb ? $cb() : null;
941 
942  // returning null would result in this being re-called every access
943  return $id ?? false;
944  }
945 
952  private static function initSpeculativePageId( ParserOptions $popt ) {
953  $cb = $popt->getOption( 'speculativePageIdCallback' );
954  $id = $cb ? $cb() : null;
955 
956  // returning null would result in this being re-called every access
957  return $id ?? false;
958  }
959 
966  public function setSpeculativeRevIdCallback( $x ) {
967  $this->setOption( 'speculativeRevId', null ); // reset
968  return $this->setOption( 'speculativeRevIdCallback', $x );
969  }
970 
977  public function setSpeculativePageIdCallback( $x ) {
978  $this->setOption( 'speculativePageId', null ); // reset
979  return $this->setOption( 'speculativePageIdCallback', $x );
980  }
981 
986  public function getTimestamp() {
987  if ( !isset( $this->mTimestamp ) ) {
988  $this->mTimestamp = wfTimestampNow();
989  }
990  return $this->mTimestamp;
991  }
992 
998  public function setTimestamp( $x ) {
999  return wfSetVar( $this->mTimestamp, $x );
1000  }
1001 
1012  public function setRedirectTarget( $title ) {
1013  $this->redirectTarget = $title;
1014  }
1015 
1022  public function getRedirectTarget() {
1023  return $this->redirectTarget;
1024  }
1025 
1032  public function addExtraKey( $key ) {
1033  $this->mExtraKey .= '!' . $key;
1034  }
1035 
1040  public function getUser() {
1041  return $this->mUser;
1042  }
1043 
1050  public function __construct( $user = null, $lang = null ) {
1051  if ( $user === null ) {
1052  global $wgUser;
1053  if ( $wgUser === null ) {
1054  $user = new User;
1055  } else {
1056  $user = $wgUser;
1057  }
1058  }
1059  if ( $lang === null ) {
1060  global $wgLang;
1062  $lang = $wgLang;
1063  }
1064  $this->initialiseFromUser( $user, $lang );
1065  }
1066 
1074  public static function newFromAnon() {
1075  return new ParserOptions( new User,
1076  MediaWikiServices::getInstance()->getContentLanguage() );
1077  }
1078 
1088  public static function newFromUser( $user ) {
1089  return new ParserOptions( $user );
1090  }
1091 
1101  public static function newFromUserAndLang( User $user, Language $lang ) {
1102  return new ParserOptions( $user, $lang );
1103  }
1104 
1113  public static function newFromContext( IContextSource $context ) {
1114  return new ParserOptions( $context->getUser(), $context->getLanguage() );
1115  }
1116 
1135  public static function newCanonical( $context = null, $userLang = null ) {
1136  if ( $context instanceof IContextSource ) {
1137  $ret = self::newFromContext( $context );
1138  } elseif ( $context === 'canonical' ) {
1139  $ret = self::newFromAnon();
1140  } elseif ( $context instanceof User || $context === null ) {
1141  if ( $context === null ) {
1142  wfDeprecated( __METHOD__ . ' with no user', '1.35' );
1143  }
1144  $ret = new self( $context, $userLang );
1145  } else {
1146  throw new InvalidArgumentException(
1147  '$context must be an IContextSource, the string "canonical", a User, or null'
1148  );
1149  }
1150 
1151  foreach ( self::getCanonicalOverrides() as $k => $v ) {
1152  $ret->setOption( $k, $v );
1153  }
1154  return $ret;
1155  }
1156 
1166  private static function getDefaults() {
1173 
1174  if ( self::$defaults === null ) {
1175  // *UPDATE* ParserOptions::matches() if any of this changes as needed
1176  self::$defaults = [
1177  'dateformat' => null,
1178  'tidy' => true,
1179  'interfaceMessage' => false,
1180  'targetLanguage' => null,
1181  'removeComments' => true,
1182  'enableLimitReport' => false,
1183  'preSaveTransform' => true,
1184  'isPreview' => false,
1185  'isSectionPreview' => false,
1186  'printable' => false,
1187  'allowUnsafeRawHtml' => true,
1188  'wrapclass' => 'mw-parser-output',
1189  'currentRevisionCallback' => [ Parser::class, 'statelessFetchRevision' ],
1190  'currentRevisionRecordCallback' => [ Parser::class, 'statelessFetchRevisionRecord' ],
1191  'templateCallback' => [ Parser::class, 'statelessFetchTemplate' ],
1192  'speculativeRevIdCallback' => null,
1193  'speculativeRevId' => null,
1194  'speculativePageIdCallback' => null,
1195  'speculativePageId' => null,
1196  ];
1197 
1198  Hooks::runner()->onParserOptionsRegister(
1199  self::$defaults,
1200  self::$inCacheKey,
1201  self::$lazyOptions
1202  );
1203 
1204  ksort( self::$inCacheKey );
1205  }
1206 
1207  // Unit tests depend on being able to modify the globals at will
1208  return self::$defaults + [
1209  'interwikiMagic' => $wgInterwikiMagic,
1210  'allowExternalImages' => $wgAllowExternalImages,
1211  'allowExternalImagesFrom' => $wgAllowExternalImagesFrom,
1212  'enableImageWhitelist' => $wgEnableImageWhitelist,
1213  'allowSpecialInclusion' => $wgAllowSpecialInclusion,
1214  'maxIncludeSize' => $wgMaxArticleSize * 1024,
1215  'maxPPNodeCount' => $wgMaxPPNodeCount,
1216  'maxPPExpandDepth' => $wgMaxPPExpandDepth,
1217  'maxTemplateDepth' => $wgMaxTemplateDepth,
1218  'expensiveParserFunctionLimit' => $wgExpensiveParserFunctionLimit,
1219  'externalLinkTarget' => $wgExternalLinkTarget,
1220  'cleanSignatures' => $wgCleanSignatures,
1221  'disableContentConversion' => $wgDisableLangConversion,
1222  'disableTitleConversion' => $wgDisableLangConversion || $wgDisableTitleConversion,
1223  'magicISBNLinks' => $wgEnableMagicLinks['ISBN'],
1224  'magicPMIDLinks' => $wgEnableMagicLinks['PMID'],
1225  'magicRFCLinks' => $wgEnableMagicLinks['RFC'],
1226  'numberheadings' => User::getDefaultOption( 'numberheadings' ),
1227  'thumbsize' => User::getDefaultOption( 'thumbsize' ),
1228  'stubthreshold' => 0,
1229  'userlang' => MediaWikiServices::getInstance()->getContentLanguage(),
1230  ];
1231  }
1232 
1242  private static function getCanonicalOverrides() {
1244 
1245  return [
1246  'enableLimitReport' => $wgEnableParserLimitReporting,
1247  ];
1248  }
1249 
1256  private function initialiseFromUser( $user, $lang ) {
1257  $this->options = self::getDefaults();
1258 
1259  $this->mUser = $user;
1260  $this->options['numberheadings'] = $user->getOption( 'numberheadings' );
1261  $this->options['thumbsize'] = $user->getOption( 'thumbsize' );
1262  $this->options['stubthreshold'] = $user->getStubThreshold();
1263  $this->options['userlang'] = $lang;
1264  }
1265 
1275  public function matches( ParserOptions $other ) {
1276  // Compare most options
1277  $options = array_keys( $this->options );
1278  $options = array_diff( $options, [
1279  'enableLimitReport', // only affects HTML comments
1280  ] );
1281  foreach ( $options as $option ) {
1282  // Resolve any lazy options
1283  $this->lazyLoadOption( $option );
1284  $other->lazyLoadOption( $option );
1285 
1286  $o1 = $this->optionToString( $this->options[$option] );
1287  $o2 = $this->optionToString( $other->options[$option] );
1288  if ( $o1 !== $o2 ) {
1289  return false;
1290  }
1291  }
1292 
1293  // Compare most other fields
1294  $fields = array_keys( get_class_vars( __CLASS__ ) );
1295  $fields = array_diff( $fields, [
1296  'defaults', // static
1297  'lazyOptions', // static
1298  'inCacheKey', // static
1299  'options', // Already checked above
1300  'onAccessCallback', // only used for ParserOutput option tracking
1301  ] );
1302  foreach ( $fields as $field ) {
1303  if ( !is_object( $this->$field ) && $this->$field !== $other->$field ) {
1304  return false;
1305  }
1306  }
1307 
1308  return true;
1309  }
1310 
1316  public function matchesForCacheKey( ParserOptions $other ) {
1317  foreach ( self::allCacheVaryingOptions() as $option ) {
1318  // Populate any lazy options
1319  $this->lazyLoadOption( $option );
1320  $other->lazyLoadOption( $option );
1321 
1322  $o1 = $this->optionToString( $this->options[$option] );
1323  $o2 = $this->optionToString( $other->options[$option] );
1324  if ( $o1 !== $o2 ) {
1325  return false;
1326  }
1327  }
1328 
1329  return true;
1330  }
1331 
1337  public function registerWatcher( $callback ) {
1338  $this->onAccessCallback = $callback;
1339  }
1340 
1349  public function optionUsed( $optionName ) {
1350  if ( $this->onAccessCallback ) {
1351  call_user_func( $this->onAccessCallback, $optionName );
1352  }
1353  }
1354 
1360  public static function allCacheVaryingOptions() {
1361  // Trigger a call to the 'ParserOptionsRegister' hook if it hasn't
1362  // already been called.
1363  if ( self::$defaults === null ) {
1365  }
1366  return array_keys( array_filter( self::$inCacheKey ) );
1367  }
1368 
1374  private function optionToString( $value ) {
1375  if ( $value === true ) {
1376  return '1';
1377  } elseif ( $value === false ) {
1378  return '0';
1379  } elseif ( $value === null ) {
1380  return '';
1381  } elseif ( $value instanceof Language ) {
1382  return $value->getCode();
1383  } elseif ( is_array( $value ) ) {
1384  return '[' . implode( ',', array_map( [ $this, 'optionToString' ], $value ) ) . ']';
1385  } else {
1386  return (string)$value;
1387  }
1388  }
1389 
1402  public function optionsHash( $forOptions, $title = null ) {
1403  global $wgRenderHashAppend;
1404 
1406 
1407  // Resolve any lazy options
1408  $lazyOpts = array_intersect( $forOptions, $inCacheKey, array_keys( self::$lazyOptions ) );
1409  foreach ( $lazyOpts as $k ) {
1410  $this->lazyLoadOption( $k );
1411  }
1412 
1415 
1416  // We only include used options with non-canonical values in the key
1417  // so adding a new option doesn't invalidate the entire parser cache.
1418  // The drawback to this is that changing the default value of an option
1419  // requires manual invalidation of existing cache entries, as mentioned
1420  // in the docs on the relevant methods and hooks.
1421  $values = [];
1422  foreach ( array_intersect( $inCacheKey, $forOptions ) as $option ) {
1423  $v = $this->optionToString( $options[$option] );
1424  $d = $this->optionToString( $defaults[$option] );
1425  if ( $v !== $d ) {
1426  $values[] = "$option=$v";
1427  }
1428  }
1429 
1430  $confstr = $values ? implode( '!', $values ) : 'canonical';
1431 
1432  // add in language specific options, if any
1433  // @todo FIXME: This is just a way of retrieving the url/user preferred variant
1434 
1435  $lang = $title ? $title->getPageLanguage() :
1436  MediaWikiServices::getInstance()->getContentLanguage();
1437  $converter = MediaWikiServices::getInstance()->getLanguageConverterFactory()
1438  ->getLanguageConverter( $lang );
1439  $confstr .= $converter->getExtraHashOptions();
1440 
1441  $confstr .= $wgRenderHashAppend;
1442 
1443  if ( $this->mExtraKey != '' ) {
1444  $confstr .= $this->mExtraKey;
1445  }
1446 
1447  // Give a chance for extensions to modify the hash, if they have
1448  // extra options or other effects on the parser cache.
1449  Hooks::runner()->onPageRenderingHash( $confstr, $this->getUser(), $forOptions );
1450 
1451  // Make it a valid memcached key fragment
1452  $confstr = str_replace( ' ', '_', $confstr );
1453 
1454  return $confstr;
1455  }
1456 
1462  public function isSafeToCache() {
1464  foreach ( $this->options as $option => $value ) {
1465  if ( empty( self::$inCacheKey[$option] ) ) {
1466  $v = $this->optionToString( $value );
1467  $d = $this->optionToString( $defaults[$option] );
1468  if ( $v !== $d ) {
1469  return false;
1470  }
1471  }
1472  }
1473  return true;
1474  }
1475 
1486  public function setupFakeRevision( $title, $content, $user ) {
1487  $oldCallback = $this->setCurrentRevisionRecordCallback(
1488  function (
1489  $titleToCheck, $parser = null ) use ( $title, $content, $user, &$oldCallback
1490  ) {
1491  if ( $titleToCheck->equals( $title ) ) {
1492  $revRecord = new MutableRevisionRecord( $title );
1493  $revRecord->setContent( SlotRecord::MAIN, $content );
1494  $revRecord->setUser( $user );
1495  $revRecord->setTimestamp( MWTimestamp::now( TS_MW ) );
1496  $revRecord->setPageId( $title->getArticleID() );
1497  $revRecord->setParentId( $title->getLatestRevID() );
1498  return $revRecord;
1499  } else {
1500  return call_user_func( $oldCallback, $titleToCheck, $parser );
1501  }
1502  }
1503  );
1504 
1505  global $wgHooks;
1506  $wgHooks['TitleExists'][] =
1507  function ( $titleToCheck, &$exists ) use ( $title ) {
1508  if ( $titleToCheck->equals( $title ) ) {
1509  $exists = true;
1510  }
1511  };
1512  end( $wgHooks['TitleExists'] );
1513  $key = key( $wgHooks['TitleExists'] );
1514  $linkCache = MediaWikiServices::getInstance()->getLinkCache();
1515  $linkCache->clearBadLink( $title->getPrefixedDBkey() );
1516  return new ScopedCallback( function () use ( $title, $key, $linkCache ) {
1517  global $wgHooks;
1518  unset( $wgHooks['TitleExists'][$key] );
1519  $linkCache->clearLink( $title );
1520  } );
1521  }
1522 }
1523 
User\getDefaultOption
static getDefaultOption( $opt)
Get a given default option value.
Definition: User.php:1539
ParserOptions\setMaxIncludeSize
setMaxIncludeSize( $x)
Maximum size of template expansions, in bytes.
Definition: ParserOptions.php:366
ParserOptions\getMagicPMIDLinks
getMagicPMIDLinks()
Are magic PMID links enabled?
Definition: ParserOptions.php:729
ParserOptions
Set options of the Parser.
Definition: ParserOptions.php:44
ParserOptions\setOptionLegacy
setOptionLegacy( $name, $value)
Legacy implementation.
Definition: ParserOptions.php:168
ParserOptions\getAllowExternalImagesFrom
getAllowExternalImagesFrom()
External images to allow.
Definition: ParserOptions.php:223
ParserOptions\getWrapOutputClass
getWrapOutputClass()
Class to use to wrap output from Parser::parse()
Definition: ParserOptions.php:777
ParserOptions\getExpensiveParserFunctionLimit
getExpensiveParserFunctionLimit()
Maximum number of calls per parse to expensive parser functions.
Definition: ParserOptions.php:417
ParserOptions\setTidy
setTidy( $x)
Use tidy to cleanup output HTML?
Definition: ParserOptions.php:312
ParserOptions\getIsSectionPreview
getIsSectionPreview()
Parsing the page for a "preview" operation on a single section?
Definition: ParserOptions.php:592
$wgMaxArticleSize
$wgMaxArticleSize
Maximum article size in kilobytes.
Definition: DefaultSettings.php:2407
ParserOptions\getRemoveComments
getRemoveComments()
Remove HTML comments.
Definition: ParserOptions.php:436
ParserOptions\setAllowUnsafeRawHtml
setAllowUnsafeRawHtml( $x)
If the wiki is configured to allow raw html ($wgRawHtml = true) is it allowed in the specific case of...
Definition: ParserOptions.php:768
ParserOptions\disableContentConversion
disableContentConversion( $x=true)
Whether content conversion should be disabled.
Definition: ParserOptions.php:516
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:154
$lang
if(!isset( $args[0])) $lang
Definition: testCompression.php:37
ParserOptions\initialiseFromUser
initialiseFromUser( $user, $lang)
Get user options.
Definition: ParserOptions.php:1256
wfSetVar
wfSetVar(&$dest, $source, $force=false)
Sets dest to source and returns the original value of dest If source is NULL, it just returns the val...
Definition: GlobalFunctions.php:1543
$wgMaxTemplateDepth
$wgMaxTemplateDepth
Maximum recursion depth for templates within templates.
Definition: DefaultSettings.php:4564
ParserOptions\getIsPreview
getIsPreview()
Parsing the page for a "preview" operation?
Definition: ParserOptions.php:575
ParserOptions\getDisableTitleConversion
getDisableTitleConversion()
Whether title conversion should be disabled.
Definition: ParserOptions.php:524
ParserOptions\setAllowExternalImages
setAllowExternalImages( $x)
Allow all external images inline?
Definition: ParserOptions.php:211
ParserOptions\setTemplateCallback
setTemplateCallback( $x)
Callback for template fetching; first argument to call_user_func().
Definition: ParserOptions.php:900
ParserOptions\setIsPreview
setIsPreview( $x)
Parsing the page for a "preview" operation?
Definition: ParserOptions.php:584
ParserOptions\setTargetLanguage
setTargetLanguage( $x)
Target language for the parse.
Definition: ParserOptions.php:349
ParserOptions\getInterfaceMessage
getInterfaceMessage()
Parsing an interface message?
Definition: ParserOptions.php:323
ParserOptions\setIsSectionPreview
setIsSectionPreview( $x)
Parsing the page for a "preview" operation on a single section?
Definition: ParserOptions.php:601
ParserOptions\getSpeculativeRevId
getSpeculativeRevId()
A guess for {{REVISIONID}}, calculated using the callback provided via setSpeculativeRevIdCallback().
Definition: ParserOptions.php:914
ParserOptions\newFromAnon
static newFromAnon()
Get a ParserOptions object for an anonymous user.
Definition: ParserOptions.php:1074
ParserOptions\setEnableImageWhitelist
setEnableImageWhitelist( $x)
Use the on-wiki external image whitelist?
Definition: ParserOptions.php:257
$wgDisableTitleConversion
$wgDisableTitleConversion
Whether to enable language variant conversion for links.
Definition: DefaultSettings.php:3256
ParserOptions\setWrapOutputClass
setWrapOutputClass( $className)
CSS class to use to wrap output from Parser::parse()
Definition: ParserOptions.php:788
ParserOptions\setSpeculativeRevIdCallback
setSpeculativeRevIdCallback( $x)
Callback to generate a guess for {{REVISIONID}}.
Definition: ParserOptions.php:966
ParserOptions\disableTitleConversion
disableTitleConversion( $x=true)
Whether title conversion should be disabled.
Definition: ParserOptions.php:533
ParserOptions\initDateFormat
static initDateFormat(ParserOptions $popt)
Lazy initializer for dateFormat.
Definition: ParserOptions.php:652
ParserOptions\getIsPrintable
getIsPrintable()
Parsing the printable version of the page?
Definition: ParserOptions.php:609
ParserOptions\setCurrentRevisionCallback
setCurrentRevisionCallback( $x)
Callback for current revision fetching; first argument to call_user_func().
Definition: ParserOptions.php:871
ParserOptions\$inCacheKey
static array $inCacheKey
Specify options that are included in the cache key.
Definition: ParserOptions.php:67
ParserOptions\setMaxTemplateDepth
setMaxTemplateDepth( $x)
Maximum recursion depth for templates within templates.
Definition: ParserOptions.php:408
ParserOptions\getMagicRFCLinks
getMagicRFCLinks()
Are magic RFC links enabled?
Definition: ParserOptions.php:738
ParserOptions\getUserLangObj
getUserLangObj()
Get the user language used by the parser for this page and split the parser cache.
Definition: ParserOptions.php:682
ParserOptions\registerWatcher
registerWatcher( $callback)
Registers a callback for tracking which ParserOptions which are used.
Definition: ParserOptions.php:1337
ParserOptions\setupFakeRevision
setupFakeRevision( $title, $content, $user)
Sets a hook to force that a page exists, and sets a current revision callback to return a revision wi...
Definition: ParserOptions.php:1486
ParserOptions\getDateFormat
getDateFormat()
Date format index.
Definition: ParserOptions.php:643
Revision
Definition: Revision.php:40
ParserOptions\setOption
setOption( $name, $value)
Set an option, generically.
Definition: ParserOptions.php:151
ParserOptions\initSpeculativeRevId
static initSpeculativeRevId(ParserOptions $popt)
Callback registered with ParserOptions::$lazyOptions, triggered by getSpeculativeRevId().
Definition: ParserOptions.php:938
wfDeprecatedMsg
wfDeprecatedMsg( $msg, $version=false, $component=false, $callerOffset=2)
Log a deprecation warning with arbitrary message text.
Definition: GlobalFunctions.php:1058
ParserOptions\setNumberHeadings
setNumberHeadings( $x)
Automatically number headings?
Definition: ParserOptions.php:275
$wgHooks
$wgHooks
Global list of hooks.
Definition: DefaultSettings.php:7928
ParserOptions\getCanonicalOverrides
static getCanonicalOverrides()
Get "canonical" non-default option values.
Definition: ParserOptions.php:1242
wfDeprecated
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that $function is deprecated.
Definition: GlobalFunctions.php:1026
ParserOptions\getRedirectTarget
getRedirectTarget()
Get the previously-set redirect target.
Definition: ParserOptions.php:1022
ParserOptions\newFromUserAndLang
static newFromUserAndLang(User $user, Language $lang)
Get a ParserOptions object from a given user and language.
Definition: ParserOptions.php:1101
ParserOptions\setUserLang
setUserLang( $x)
Set the user language used by the parser for this page and split the parser cache.
Definition: ParserOptions.php:707
ParserOptions\getAllowSpecialInclusion
getAllowSpecialInclusion()
Allow inclusion of special pages?
Definition: ParserOptions.php:283
$wgAllowExternalImagesFrom
$wgAllowExternalImagesFrom
If the above is false, you can specify an exception here.
Definition: DefaultSettings.php:4610
ParserOptions\getTidy
getTidy()
Use tidy to cleanup output HTML?
Definition: ParserOptions.php:301
ParserOptions\getMaxIncludeSize
getMaxIncludeSize()
Maximum size of template expansions, in bytes.
Definition: ParserOptions.php:357
ParserOptions\$mTimestamp
string null $mTimestamp
Timestamp used for {{CURRENTDAY}} etc.
Definition: ParserOptions.php:87
$wgLang
$wgLang
Definition: Setup.php:776
$wgExpensiveParserFunctionLimit
$wgExpensiveParserFunctionLimit
Maximum number of calls per parse to expensive parser functions such as PAGESINCATEGORY.
Definition: DefaultSettings.php:4720
ParserOptions\setThumbSize
setThumbSize( $x)
Thumb size preferred by the user.
Definition: ParserOptions.php:550
ParserOptions\getEnableImageWhitelist
getEnableImageWhitelist()
Use the on-wiki external image whitelist?
Definition: ParserOptions.php:246
$wgInterwikiMagic
$wgInterwikiMagic
Treat language links as magic connectors, not inline links.
Definition: DefaultSettings.php:3124
ParserOptions\setExternalLinkTarget
setExternalLinkTarget( $x)
Target attribute for external links.
Definition: ParserOptions.php:499
ParserOptions\setDateFormat
setDateFormat( $x)
Date format index.
Definition: ParserOptions.php:661
ParserOptions\getTargetLanguage
getTargetLanguage()
Target language for the parse.
Definition: ParserOptions.php:340
$title
$title
Definition: testCompression.php:38
ParserOptions\initSpeculativePageId
static initSpeculativePageId(ParserOptions $popt)
Callback registered with ParserOptions::$lazyOptions, triggered by getSpeculativePageId().
Definition: ParserOptions.php:952
ParserOptions\setAllowSpecialInclusion
setAllowSpecialInclusion( $x)
Allow inclusion of special pages?
Definition: ParserOptions.php:292
$wgMaxPPExpandDepth
$wgMaxPPExpandDepth
Definition: DefaultSettings.php:4569
ParserOptions\getDefaults
static getDefaults()
Get default option values.
Definition: ParserOptions.php:1166
ParserOptions\getExternalLinkTarget
getExternalLinkTarget()
Target attribute for external links.
Definition: ParserOptions.php:490
ParserOptions\$onAccessCallback
callable null $onAccessCallback
Function to be called when an option is accessed.
Definition: ParserOptions.php:101
$wgEnableMagicLinks
$wgEnableMagicLinks
Enable the magic links feature of automatically turning ISBN xxx, PMID xxx, RFC xxx into links.
Definition: DefaultSettings.php:4745
wfTimestampNow
wfTimestampNow()
Convenience function; returns MediaWiki timestamp for the present time.
Definition: GlobalFunctions.php:1837
ParserOptions\getStubThreshold
getStubThreshold()
Thumb size preferred by the user.
Definition: ParserOptions.php:558
$wgExternalLinkTarget
$wgExternalLinkTarget
Set a default target for external links, e.g.
Definition: DefaultSettings.php:4673
ParserOptions\$options
array $options
Current values for all options that are relevant for caching.
Definition: ParserOptions.php:80
ParserOptions\getUserLang
getUserLang()
Same as getUserLangObj() but returns a string instead.
Definition: ParserOptions.php:698
$wgDisableLangConversion
$wgDisableLangConversion
Whether to enable language variant conversion.
Definition: DefaultSettings.php:3251
ParserOptions\getPreSaveTransform
getPreSaveTransform()
Transform wiki markup when saving the page?
Definition: ParserOptions.php:626
ParserOptions\setStubThreshold
setStubThreshold( $x)
Thumb size preferred by the user.
Definition: ParserOptions.php:567
ParserOptions\getOption
getOption( $name)
Fetch an option and track that is was accessed.
Definition: ParserOptions.php:122
ParserOptions\$mExtraKey
$mExtraKey
Appended to the options hash.
Definition: ParserOptions.php:114
ParserOptions\getAllowUnsafeRawHtml
getAllowUnsafeRawHtml()
If the wiki is configured to allow raw html ($wgRawHtml = true) is it allowed in the specific case of...
Definition: ParserOptions.php:756
ParserOptions\getDisableContentConversion
getDisableContentConversion()
Whether content conversion should be disabled.
Definition: ParserOptions.php:507
ParserOptions\optionToString
optionToString( $value)
Convert an option to a string value.
Definition: ParserOptions.php:1374
ParserOptions\matchesForCacheKey
matchesForCacheKey(ParserOptions $other)
Definition: ParserOptions.php:1316
ParserOptions\optionUsed
optionUsed( $optionName)
Called when an option is accessed.
Definition: ParserOptions.php:1349
$content
$content
Definition: router.php:76
ParserOptions\getSpeculativePageId
getSpeculativePageId()
A guess for {{PAGEID}}, calculated using the callback provided via setSpeculativeRevPageCallback().
Definition: ParserOptions.php:928
ParserOptions\setTimestamp
setTimestamp( $x)
Timestamp used for {{CURRENTDAY}} etc.
Definition: ParserOptions.php:998
ParserOptions\setSpeculativePageIdCallback
setSpeculativePageIdCallback( $x)
Callback to generate a guess for {{PAGEID}}.
Definition: ParserOptions.php:977
ParserOptions\setCleanSignatures
setCleanSignatures( $x)
Clean up signature texts?
Definition: ParserOptions.php:482
ParserOptions\newFromContext
static newFromContext(IContextSource $context)
Get a ParserOptions object from a IContextSource object.
Definition: ParserOptions.php:1113
Revision\MutableRevisionRecord
Definition: MutableRevisionRecord.php:45
ParserOptions\getCurrentRevisionCallback
getCurrentRevisionCallback()
Callback for current revision fetching; first argument to call_user_func().
Definition: ParserOptions.php:804
Hooks\runner
static runner()
Get a HookRunner instance for calling hooks using the new interfaces.
Definition: Hooks.php:172
$wgEnableParserLimitReporting
$wgEnableParserLimitReporting
Whether to include the NewPP limit report as a HTML comment.
Definition: DefaultSettings.php:7784
ParserOptions\getTemplateCallback
getTemplateCallback()
Callback for template fetching; first argument to call_user_func().
Definition: ParserOptions.php:891
ParserOptions\newCanonical
static newCanonical( $context=null, $userLang=null)
Creates a "canonical" ParserOptions object.
Definition: ParserOptions.php:1135
ParserOptions\setRemoveComments
setRemoveComments( $x)
Remove HTML comments.
Definition: ParserOptions.php:446
ParserOptions\setInterwikiMagic
setInterwikiMagic( $x)
Specify whether to extract interlanguage links.
Definition: ParserOptions.php:192
IContextSource\getUser
getUser()
ParserOptions\lazyLoadOption
lazyLoadOption( $name)
Definition: ParserOptions.php:137
ParserOptions\setRedirectTarget
setRedirectTarget( $title)
Set the redirect target.
Definition: ParserOptions.php:1012
ParserOptions\setExpensiveParserFunctionLimit
setExpensiveParserFunctionLimit( $x)
Maximum number of calls per parse to expensive parser functions.
Definition: ParserOptions.php:427
ParserOptions\getTimestamp
getTimestamp()
Timestamp used for {{CURRENTDAY}} etc.
Definition: ParserOptions.php:986
ParserOptions\setMaxPPNodeCount
setMaxPPNodeCount( $x)
Maximum number of nodes touched by PPFrame::expand()
Definition: ParserOptions.php:383
IContextSource
Interface for objects which can provide a MediaWiki context on request.
Definition: IContextSource.php:55
ParserOptions\getCleanSignatures
getCleanSignatures()
Clean up signature texts?
Definition: ParserOptions.php:472
ParserOptions\$redirectTarget
Title null $redirectTarget
If the page being parsed is a redirect, this should hold the redirect target.
Definition: ParserOptions.php:109
ParserOptions\setAllowExternalImagesFrom
setAllowExternalImagesFrom( $x)
External images to allow.
Definition: ParserOptions.php:237
ParserOptions\matches
matches(ParserOptions $other)
Check if these options match that of another options set.
Definition: ParserOptions.php:1275
ParserOptions\enableLimitReport
enableLimitReport( $x=true)
Enable limit report in an HTML comment on output.
Definition: ParserOptions.php:463
Title
Represents a title within MediaWiki.
Definition: Title.php:42
ParserOptions\__construct
__construct( $user=null, $lang=null)
Definition: ParserOptions.php:1050
ParserOptions\getInterwikiMagic
getInterwikiMagic()
Whether to extract interlanguage links.
Definition: ParserOptions.php:183
ParserOptions\$lazyOptions
static callable[] $lazyOptions
Lazy-loaded options.
Definition: ParserOptions.php:57
ParserOptions\$mUser
User $mUser
Stored user object.
Definition: ParserOptions.php:94
ParserOptions\setInterfaceMessage
setInterfaceMessage( $x)
Parsing an interface message?
Definition: ParserOptions.php:332
ParserOptions\$defaults
static array null $defaults
Default values for all options that are relevant for caching.
Definition: ParserOptions.php:51
ParserOptions\allCacheVaryingOptions
static allCacheVaryingOptions()
Return all option keys that vary the options hash.
Definition: ParserOptions.php:1360
$wgCleanSignatures
$wgCleanSignatures
If true, removes (by substituting) templates in signatures.
Definition: DefaultSettings.php:4591
ParserOptions\getUser
getUser()
Current user.
Definition: ParserOptions.php:1040
ParserOptions\getThumbSize
getThumbSize()
Thumb size preferred by the user.
Definition: ParserOptions.php:541
ParserOptions\getMagicISBNLinks
getMagicISBNLinks()
Are magic ISBN links enabled?
Definition: ParserOptions.php:720
ParserOptions\setIsPrintable
setIsPrintable( $x)
Parsing the printable version of the page?
Definition: ParserOptions.php:618
ParserOptions\getMaxPPNodeCount
getMaxPPNodeCount()
Maximum number of nodes touched by PPFrame::expand()
Definition: ParserOptions.php:374
$wgRenderHashAppend
$wgRenderHashAppend
Append a configured value to the parser cache and the sitenotice key so that they can be kept separat...
Definition: DefaultSettings.php:2804
ParserOptions\getCurrentRevisionRecordCallback
getCurrentRevisionRecordCallback()
Callback for current revision fetching; first argument to call_user_func().
Definition: ParserOptions.php:842
ParserOptions\getMaxPPExpandDepth
getMaxPPExpandDepth()
Maximum recursion depth in PPFrame::expand()
Definition: ParserOptions.php:391
ParserOptions\getEnableLimitReport
getEnableLimitReport()
Enable limit report in an HTML comment on output.
Definition: ParserOptions.php:454
ParserOptions\getNumberHeadings
getNumberHeadings()
Automatically number headings?
Definition: ParserOptions.php:266
ParserOptions\isSafeToCache
isSafeToCache()
Test whether these options are safe to cache.
Definition: ParserOptions.php:1462
ParserOptions\getMaxTemplateDepth
getMaxTemplateDepth()
Maximum recursion depth for templates within templates.
Definition: ParserOptions.php:399
ParserOptions\setPreSaveTransform
setPreSaveTransform( $x)
Transform wiki markup when saving the page?
Definition: ParserOptions.php:635
User
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition: User.php:55
StubObject\unstub
static unstub(&$obj)
Unstubs an object, if it is a stub object.
Definition: StubObject.php:97
$wgMaxPPNodeCount
$wgMaxPPNodeCount
A complexity limit on template expansion: the maximum number of nodes visited by PPFrame::expand()
Definition: DefaultSettings.php:4556
ParserOptions\setCurrentRevisionRecordCallback
setCurrentRevisionRecordCallback( $x)
Callback for current revision fetching; first argument to call_user_func().
Definition: ParserOptions.php:883
Language
Internationalisation code See https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation for more...
Definition: Language.php:41
ParserOptions\optionsHash
optionsHash( $forOptions, $title=null)
Generate a hash string with the values set on these ParserOptions for the keys given in the array.
Definition: ParserOptions.php:1402
IContextSource\getLanguage
getLanguage()
Revision\SlotRecord
Value object representing a content slot associated with a page revision.
Definition: SlotRecord.php:39
ParserOptions\getAllowExternalImages
getAllowExternalImages()
Allow all external images inline?
Definition: ParserOptions.php:200
ParserOptions\newFromUser
static newFromUser( $user)
Get a ParserOptions object from a given user.
Definition: ParserOptions.php:1088
$wgAllowExternalImages
$wgAllowExternalImages
Whether to allow inline image pointing to other websites.
Definition: DefaultSettings.php:4596
$wgEnableImageWhitelist
$wgEnableImageWhitelist
If $wgAllowExternalImages is false, you can allow an on-wiki allow list of regular expression fragmen...
Definition: DefaultSettings.php:4623
ParserOptions\addExtraKey
addExtraKey( $key)
Extra key that should be present in the parser cache key.
Definition: ParserOptions.php:1032
$wgAllowSpecialInclusion
$wgAllowSpecialInclusion
Allow special page inclusions such as {{Special:Allpages}}.
Definition: DefaultSettings.php:8368