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 
302  public function setTidy( $x ) {
303  wfDeprecated( __METHOD__, '1.35' );
304  // This has no effect.
305  return null;
306  }
307 
312  public function getInterfaceMessage() {
313  return $this->getOption( 'interfaceMessage' );
314  }
315 
321  public function setInterfaceMessage( $x ) {
322  return $this->setOptionLegacy( 'interfaceMessage', $x );
323  }
324 
329  public function getTargetLanguage() {
330  return $this->getOption( 'targetLanguage' );
331  }
332 
338  public function setTargetLanguage( $x ) {
339  return $this->setOption( 'targetLanguage', $x );
340  }
341 
346  public function getMaxIncludeSize() {
347  return $this->getOption( 'maxIncludeSize' );
348  }
349 
355  public function setMaxIncludeSize( $x ) {
356  return $this->setOptionLegacy( 'maxIncludeSize', $x );
357  }
358 
363  public function getMaxPPNodeCount() {
364  return $this->getOption( 'maxPPNodeCount' );
365  }
366 
372  public function setMaxPPNodeCount( $x ) {
373  return $this->setOptionLegacy( 'maxPPNodeCount', $x );
374  }
375 
380  public function getMaxPPExpandDepth() {
381  return $this->getOption( 'maxPPExpandDepth' );
382  }
383 
388  public function getMaxTemplateDepth() {
389  return $this->getOption( 'maxTemplateDepth' );
390  }
391 
397  public function setMaxTemplateDepth( $x ) {
398  return $this->setOptionLegacy( 'maxTemplateDepth', $x );
399  }
400 
407  return $this->getOption( 'expensiveParserFunctionLimit' );
408  }
409 
416  public function setExpensiveParserFunctionLimit( $x ) {
417  return $this->setOptionLegacy( 'expensiveParserFunctionLimit', $x );
418  }
419 
425  public function getRemoveComments() {
426  return $this->getOption( 'removeComments' );
427  }
428 
435  public function setRemoveComments( $x ) {
436  return $this->setOptionLegacy( 'removeComments', $x );
437  }
438 
443  public function getEnableLimitReport() {
444  return $this->getOption( 'enableLimitReport' );
445  }
446 
452  public function enableLimitReport( $x = true ) {
453  return $this->setOptionLegacy( 'enableLimitReport', $x );
454  }
455 
461  public function getCleanSignatures() {
462  return $this->getOption( 'cleanSignatures' );
463  }
464 
471  public function setCleanSignatures( $x ) {
472  return $this->setOptionLegacy( 'cleanSignatures', $x );
473  }
474 
479  public function getExternalLinkTarget() {
480  return $this->getOption( 'externalLinkTarget' );
481  }
482 
488  public function setExternalLinkTarget( $x ) {
489  return $this->setOptionLegacy( 'externalLinkTarget', $x );
490  }
491 
496  public function getDisableContentConversion() {
497  return $this->getOption( 'disableContentConversion' );
498  }
499 
505  public function disableContentConversion( $x = true ) {
506  return $this->setOptionLegacy( 'disableContentConversion', $x );
507  }
508 
513  public function getDisableTitleConversion() {
514  return $this->getOption( 'disableTitleConversion' );
515  }
516 
522  public function disableTitleConversion( $x = true ) {
523  return $this->setOptionLegacy( 'disableTitleConversion', $x );
524  }
525 
530  public function getThumbSize() {
531  return $this->getOption( 'thumbsize' );
532  }
533 
539  public function setThumbSize( $x ) {
540  return $this->setOptionLegacy( 'thumbsize', $x );
541  }
542 
547  public function getStubThreshold() {
548  return $this->getOption( 'stubthreshold' );
549  }
550 
556  public function setStubThreshold( $x ) {
557  return $this->setOptionLegacy( 'stubthreshold', $x );
558  }
559 
564  public function getIsPreview() {
565  return $this->getOption( 'isPreview' );
566  }
567 
573  public function setIsPreview( $x ) {
574  return $this->setOptionLegacy( 'isPreview', $x );
575  }
576 
581  public function getIsSectionPreview() {
582  return $this->getOption( 'isSectionPreview' );
583  }
584 
590  public function setIsSectionPreview( $x ) {
591  return $this->setOptionLegacy( 'isSectionPreview', $x );
592  }
593 
598  public function getIsPrintable() {
599  return $this->getOption( 'printable' );
600  }
601 
607  public function setIsPrintable( $x ) {
608  return $this->setOptionLegacy( 'printable', $x );
609  }
610 
615  public function getPreSaveTransform() {
616  return $this->getOption( 'preSaveTransform' );
617  }
618 
624  public function setPreSaveTransform( $x ) {
625  return $this->setOptionLegacy( 'preSaveTransform', $x );
626  }
627 
632  public function getDateFormat() {
633  return $this->getOption( 'dateformat' );
634  }
635 
641  private static function initDateFormat( ParserOptions $popt ) {
642  return $popt->mUser->getDatePreference();
643  }
644 
650  public function setDateFormat( $x ) {
651  return $this->setOptionLegacy( 'dateformat', $x );
652  }
653 
671  public function getUserLangObj() {
672  return $this->getOption( 'userlang' );
673  }
674 
687  public function getUserLang() {
688  return $this->getUserLangObj()->getCode();
689  }
690 
696  public function setUserLang( $x ) {
697  if ( is_string( $x ) ) {
698  $x = MediaWikiServices::getInstance()->getLanguageFactory()->getLanguage( $x );
699  }
700 
701  return $this->setOptionLegacy( 'userlang', $x );
702  }
703 
709  public function getMagicISBNLinks() {
710  return $this->getOption( 'magicISBNLinks' );
711  }
712 
718  public function getMagicPMIDLinks() {
719  return $this->getOption( 'magicPMIDLinks' );
720  }
721 
727  public function getMagicRFCLinks() {
728  return $this->getOption( 'magicRFCLinks' );
729  }
730 
745  public function getAllowUnsafeRawHtml() {
746  return $this->getOption( 'allowUnsafeRawHtml' );
747  }
748 
757  public function setAllowUnsafeRawHtml( $x ) {
758  return $this->setOptionLegacy( 'allowUnsafeRawHtml', $x );
759  }
760 
766  public function getWrapOutputClass() {
767  return $this->getOption( 'wrapclass' );
768  }
769 
777  public function setWrapOutputClass( $className ) {
778  if ( $className === true ) { // DWIM, they probably want the default class name
779  $className = 'mw-parser-output';
780  }
781  if ( $className === false ) {
782  wfDeprecated( __METHOD__ . '( false )', '1.31' );
783  }
784  return $this->setOption( 'wrapclass', $className );
785  }
786 
793  public function getCurrentRevisionCallback() {
794  wfDeprecated( __METHOD__, '1.35' );
795  $revCb = $this->getOption( 'currentRevisionCallback' );
796 
797  // As a temporary measure, while both currentRevisionCallback and
798  // currentRevisionRecordCallback are supported, retrieving one that is
799  // not set first checks if the other is set, so that the end result works
800  // regardless of which setter was used, since one extension may set a
801  // RevisionCallback and another may ask for the RevisionRecordCallback
802  if ( $revCb === [ Parser::class, 'statelessFetchRevision' ] ) {
803  // currentRevisionCallback is set to the default, check if
804  // currentRevisionRecordCallback is set (and not the default)
805  $revRecordCb = $this->getOption( 'currentRevisionRecordCallback' );
806  if ( $revRecordCb !== [ Parser::class, 'statelessFetchRevisionRecord' ] ) {
807  // currentRevisionRecordCallback is set and not the default,
808  // convert it
809  $revCb = function ( Title $title, $parser = false ) use ( $revRecordCb ) {
810  $revRecord = call_user_func(
811  $revRecordCb,
812  $title,
813  $parser ?: null
814  );
815  if ( $revRecord ) {
816  return new Revision( $revRecord );
817  }
818  return false;
819  };
820  }
821  }
822  return $revCb;
823  }
824 
832  $revRecordCb = $this->getOption( 'currentRevisionRecordCallback' );
833 
834  // See explanation above
835  if ( $revRecordCb === [ Parser::class, 'statelessFetchRevisionRecord' ] ) {
836  // currentRevisionRecordCallback is set to the default, check if
837  // currentRevisionCallback is set (and not the default)
838  $revCb = $this->getOption( 'currentRevisionCallback' );
839  if ( $revCb !== [ Parser::class, 'statelessFetchRevision' ] ) {
840  // currentRevisionCallback is set and not the default, convert it
841  $revRecordCb = function ( Title $title, $parser = null ) use ( $revCb ) {
842  $rev = call_user_func( $revCb, $title, $parser ?? false );
843  if ( $rev ) {
844  return $rev->getRevisionRecord();
845  }
846  return false;
847  };
848  }
849  }
850  return $revRecordCb;
851  }
852 
860  public function setCurrentRevisionCallback( $x ) {
861  wfDeprecated( __METHOD__, '1.35' );
862  return $this->setOptionLegacy( 'currentRevisionCallback', $x );
863  }
864 
872  public function setCurrentRevisionRecordCallback( $x ) {
873  return $this->setOption( 'currentRevisionRecordCallback', $x );
874  }
875 
880  public function getTemplateCallback() {
881  return $this->getOption( 'templateCallback' );
882  }
883 
889  public function setTemplateCallback( $x ) {
890  return $this->setOptionLegacy( 'templateCallback', $x );
891  }
892 
903  public function getSpeculativeRevId() {
904  return $this->getOption( 'speculativeRevId' );
905  }
906 
917  public function getSpeculativePageId() {
918  return $this->getOption( 'speculativePageId' );
919  }
920 
927  private static function initSpeculativeRevId( ParserOptions $popt ) {
928  $cb = $popt->getOption( 'speculativeRevIdCallback' );
929  $id = $cb ? $cb() : null;
930 
931  // returning null would result in this being re-called every access
932  return $id ?? false;
933  }
934 
941  private static function initSpeculativePageId( ParserOptions $popt ) {
942  $cb = $popt->getOption( 'speculativePageIdCallback' );
943  $id = $cb ? $cb() : null;
944 
945  // returning null would result in this being re-called every access
946  return $id ?? false;
947  }
948 
955  public function setSpeculativeRevIdCallback( $x ) {
956  $this->setOption( 'speculativeRevId', null ); // reset
957  return $this->setOption( 'speculativeRevIdCallback', $x );
958  }
959 
966  public function setSpeculativePageIdCallback( $x ) {
967  $this->setOption( 'speculativePageId', null ); // reset
968  return $this->setOption( 'speculativePageIdCallback', $x );
969  }
970 
975  public function getTimestamp() {
976  if ( !isset( $this->mTimestamp ) ) {
977  $this->mTimestamp = wfTimestampNow();
978  }
979  return $this->mTimestamp;
980  }
981 
987  public function setTimestamp( $x ) {
988  return wfSetVar( $this->mTimestamp, $x );
989  }
990 
1001  public function setRedirectTarget( $title ) {
1002  $this->redirectTarget = $title;
1003  }
1004 
1011  public function getRedirectTarget() {
1012  return $this->redirectTarget;
1013  }
1014 
1021  public function addExtraKey( $key ) {
1022  $this->mExtraKey .= '!' . $key;
1023  }
1024 
1029  public function getUser() {
1030  return $this->mUser;
1031  }
1032 
1039  public function __construct( $user = null, $lang = null ) {
1040  if ( $user === null ) {
1041  global $wgUser;
1042  if ( $wgUser === null ) {
1043  $user = new User;
1044  } else {
1045  $user = $wgUser;
1046  }
1047  }
1048  if ( $lang === null ) {
1049  global $wgLang;
1051  $lang = $wgLang;
1052  }
1053  $this->initialiseFromUser( $user, $lang );
1054  }
1055 
1063  public static function newFromAnon() {
1064  return new ParserOptions( new User,
1065  MediaWikiServices::getInstance()->getContentLanguage() );
1066  }
1067 
1077  public static function newFromUser( $user ) {
1078  return new ParserOptions( $user );
1079  }
1080 
1090  public static function newFromUserAndLang( User $user, Language $lang ) {
1091  return new ParserOptions( $user, $lang );
1092  }
1093 
1102  public static function newFromContext( IContextSource $context ) {
1103  return new ParserOptions( $context->getUser(), $context->getLanguage() );
1104  }
1105 
1124  public static function newCanonical( $context = null, $userLang = null ) {
1125  if ( $context instanceof IContextSource ) {
1126  $ret = self::newFromContext( $context );
1127  } elseif ( $context === 'canonical' ) {
1128  $ret = self::newFromAnon();
1129  } elseif ( $context instanceof User || $context === null ) {
1130  if ( $context === null ) {
1131  wfDeprecated( __METHOD__ . ' with no user', '1.35' );
1132  }
1133  $ret = new self( $context, $userLang );
1134  } else {
1135  throw new InvalidArgumentException(
1136  '$context must be an IContextSource, the string "canonical", a User, or null'
1137  );
1138  }
1139 
1140  foreach ( self::getCanonicalOverrides() as $k => $v ) {
1141  $ret->setOption( $k, $v );
1142  }
1143  return $ret;
1144  }
1145 
1155  private static function getDefaults() {
1162 
1163  if ( self::$defaults === null ) {
1164  // *UPDATE* ParserOptions::matches() if any of this changes as needed
1165  self::$defaults = [
1166  'dateformat' => null,
1167  'interfaceMessage' => false,
1168  'targetLanguage' => null,
1169  'removeComments' => true,
1170  'enableLimitReport' => false,
1171  'preSaveTransform' => true,
1172  'isPreview' => false,
1173  'isSectionPreview' => false,
1174  'printable' => false,
1175  'allowUnsafeRawHtml' => true,
1176  'wrapclass' => 'mw-parser-output',
1177  'currentRevisionCallback' => [ Parser::class, 'statelessFetchRevision' ],
1178  'currentRevisionRecordCallback' => [ Parser::class, 'statelessFetchRevisionRecord' ],
1179  'templateCallback' => [ Parser::class, 'statelessFetchTemplate' ],
1180  'speculativeRevIdCallback' => null,
1181  'speculativeRevId' => null,
1182  'speculativePageIdCallback' => null,
1183  'speculativePageId' => null,
1184  ];
1185 
1186  Hooks::runner()->onParserOptionsRegister(
1187  self::$defaults,
1188  self::$inCacheKey,
1189  self::$lazyOptions
1190  );
1191 
1192  ksort( self::$inCacheKey );
1193  }
1194 
1195  // Unit tests depend on being able to modify the globals at will
1196  return self::$defaults + [
1197  'interwikiMagic' => $wgInterwikiMagic,
1198  'allowExternalImages' => $wgAllowExternalImages,
1199  'allowExternalImagesFrom' => $wgAllowExternalImagesFrom,
1200  'enableImageWhitelist' => $wgEnableImageWhitelist,
1201  'allowSpecialInclusion' => $wgAllowSpecialInclusion,
1202  'maxIncludeSize' => $wgMaxArticleSize * 1024,
1203  'maxPPNodeCount' => $wgMaxPPNodeCount,
1204  'maxPPExpandDepth' => $wgMaxPPExpandDepth,
1205  'maxTemplateDepth' => $wgMaxTemplateDepth,
1206  'expensiveParserFunctionLimit' => $wgExpensiveParserFunctionLimit,
1207  'externalLinkTarget' => $wgExternalLinkTarget,
1208  'cleanSignatures' => $wgCleanSignatures,
1209  'disableContentConversion' => $wgDisableLangConversion,
1210  'disableTitleConversion' => $wgDisableLangConversion || $wgDisableTitleConversion,
1211  'magicISBNLinks' => $wgEnableMagicLinks['ISBN'],
1212  'magicPMIDLinks' => $wgEnableMagicLinks['PMID'],
1213  'magicRFCLinks' => $wgEnableMagicLinks['RFC'],
1214  'numberheadings' => User::getDefaultOption( 'numberheadings' ),
1215  'thumbsize' => User::getDefaultOption( 'thumbsize' ),
1216  'stubthreshold' => 0,
1217  'userlang' => MediaWikiServices::getInstance()->getContentLanguage(),
1218  ];
1219  }
1220 
1230  private static function getCanonicalOverrides() {
1232 
1233  return [
1234  'enableLimitReport' => $wgEnableParserLimitReporting,
1235  ];
1236  }
1237 
1244  private function initialiseFromUser( $user, $lang ) {
1245  $this->options = self::getDefaults();
1246 
1247  $this->mUser = $user;
1248  $this->options['numberheadings'] = $user->getOption( 'numberheadings' );
1249  $this->options['thumbsize'] = $user->getOption( 'thumbsize' );
1250  $this->options['stubthreshold'] = $user->getStubThreshold();
1251  $this->options['userlang'] = $lang;
1252  }
1253 
1263  public function matches( ParserOptions $other ) {
1264  // Compare most options
1265  $options = array_keys( $this->options );
1266  $options = array_diff( $options, [
1267  'enableLimitReport', // only affects HTML comments
1268  'tidy', // Has no effect since 1.35; removed in 1.36
1269  ] );
1270  foreach ( $options as $option ) {
1271  // Resolve any lazy options
1272  $this->lazyLoadOption( $option );
1273  $other->lazyLoadOption( $option );
1274 
1275  $o1 = $this->optionToString( $this->options[$option] );
1276  $o2 = $this->optionToString( $other->options[$option] );
1277  if ( $o1 !== $o2 ) {
1278  return false;
1279  }
1280  }
1281 
1282  // Compare most other fields
1283  $fields = array_keys( get_class_vars( __CLASS__ ) );
1284  $fields = array_diff( $fields, [
1285  'defaults', // static
1286  'lazyOptions', // static
1287  'inCacheKey', // static
1288  'options', // Already checked above
1289  'onAccessCallback', // only used for ParserOutput option tracking
1290  ] );
1291  foreach ( $fields as $field ) {
1292  if ( !is_object( $this->$field ) && $this->$field !== $other->$field ) {
1293  return false;
1294  }
1295  }
1296 
1297  return true;
1298  }
1299 
1305  public function matchesForCacheKey( ParserOptions $other ) {
1306  foreach ( self::allCacheVaryingOptions() as $option ) {
1307  // Populate any lazy options
1308  $this->lazyLoadOption( $option );
1309  $other->lazyLoadOption( $option );
1310 
1311  $o1 = $this->optionToString( $this->options[$option] );
1312  $o2 = $this->optionToString( $other->options[$option] );
1313  if ( $o1 !== $o2 ) {
1314  return false;
1315  }
1316  }
1317 
1318  return true;
1319  }
1320 
1326  public function registerWatcher( $callback ) {
1327  $this->onAccessCallback = $callback;
1328  }
1329 
1338  public function optionUsed( $optionName ) {
1339  if ( $this->onAccessCallback ) {
1340  call_user_func( $this->onAccessCallback, $optionName );
1341  }
1342  }
1343 
1349  public static function allCacheVaryingOptions() {
1350  // Trigger a call to the 'ParserOptionsRegister' hook if it hasn't
1351  // already been called.
1352  if ( self::$defaults === null ) {
1354  }
1355  return array_keys( array_filter( self::$inCacheKey ) );
1356  }
1357 
1363  private function optionToString( $value ) {
1364  if ( $value === true ) {
1365  return '1';
1366  } elseif ( $value === false ) {
1367  return '0';
1368  } elseif ( $value === null ) {
1369  return '';
1370  } elseif ( $value instanceof Language ) {
1371  return $value->getCode();
1372  } elseif ( is_array( $value ) ) {
1373  return '[' . implode( ',', array_map( [ $this, 'optionToString' ], $value ) ) . ']';
1374  } else {
1375  return (string)$value;
1376  }
1377  }
1378 
1391  public function optionsHash( $forOptions, $title = null ) {
1392  global $wgRenderHashAppend;
1393 
1395 
1396  // Resolve any lazy options
1397  $lazyOpts = array_intersect( $forOptions, $inCacheKey, array_keys( self::$lazyOptions ) );
1398  foreach ( $lazyOpts as $k ) {
1399  $this->lazyLoadOption( $k );
1400  }
1401 
1404 
1405  // We only include used options with non-canonical values in the key
1406  // so adding a new option doesn't invalidate the entire parser cache.
1407  // The drawback to this is that changing the default value of an option
1408  // requires manual invalidation of existing cache entries, as mentioned
1409  // in the docs on the relevant methods and hooks.
1410  $values = [];
1411  foreach ( array_intersect( $inCacheKey, $forOptions ) as $option ) {
1412  $v = $this->optionToString( $options[$option] );
1413  $d = $this->optionToString( $defaults[$option] );
1414  if ( $v !== $d ) {
1415  $values[] = "$option=$v";
1416  }
1417  }
1418 
1419  $confstr = $values ? implode( '!', $values ) : 'canonical';
1420 
1421  // add in language specific options, if any
1422  // @todo FIXME: This is just a way of retrieving the url/user preferred variant
1423 
1424  $lang = $title ? $title->getPageLanguage() :
1425  MediaWikiServices::getInstance()->getContentLanguage();
1426  $converter = MediaWikiServices::getInstance()->getLanguageConverterFactory()
1427  ->getLanguageConverter( $lang );
1428  $confstr .= $converter->getExtraHashOptions();
1429 
1430  $confstr .= $wgRenderHashAppend;
1431 
1432  if ( $this->mExtraKey != '' ) {
1433  $confstr .= $this->mExtraKey;
1434  }
1435 
1436  // Give a chance for extensions to modify the hash, if they have
1437  // extra options or other effects on the parser cache.
1438  Hooks::runner()->onPageRenderingHash( $confstr, $this->getUser(), $forOptions );
1439 
1440  // Make it a valid memcached key fragment
1441  $confstr = str_replace( ' ', '_', $confstr );
1442 
1443  return $confstr;
1444  }
1445 
1451  public function isSafeToCache() {
1453  foreach ( $this->options as $option => $value ) {
1454  if ( empty( self::$inCacheKey[$option] ) ) {
1455  $v = $this->optionToString( $value );
1456  $d = $this->optionToString( $defaults[$option] );
1457  if ( $v !== $d ) {
1458  return false;
1459  }
1460  }
1461  }
1462  return true;
1463  }
1464 
1475  public function setupFakeRevision( $title, $content, $user ) {
1476  $oldCallback = $this->setCurrentRevisionRecordCallback(
1477  function (
1478  $titleToCheck, $parser = null ) use ( $title, $content, $user, &$oldCallback
1479  ) {
1480  if ( $titleToCheck->equals( $title ) ) {
1481  $revRecord = new MutableRevisionRecord( $title );
1482  $revRecord->setContent( SlotRecord::MAIN, $content );
1483  $revRecord->setUser( $user );
1484  $revRecord->setTimestamp( MWTimestamp::now( TS_MW ) );
1485  $revRecord->setPageId( $title->getArticleID() );
1486  $revRecord->setParentId( $title->getLatestRevID() );
1487  return $revRecord;
1488  } else {
1489  return call_user_func( $oldCallback, $titleToCheck, $parser );
1490  }
1491  }
1492  );
1493 
1494  global $wgHooks;
1495  $wgHooks['TitleExists'][] =
1496  function ( $titleToCheck, &$exists ) use ( $title ) {
1497  if ( $titleToCheck->equals( $title ) ) {
1498  $exists = true;
1499  }
1500  };
1501  end( $wgHooks['TitleExists'] );
1502  $key = key( $wgHooks['TitleExists'] );
1503  $linkCache = MediaWikiServices::getInstance()->getLinkCache();
1504  $linkCache->clearBadLink( $title->getPrefixedDBkey() );
1505  return new ScopedCallback( function () use ( $title, $key, $linkCache ) {
1506  global $wgHooks;
1507  unset( $wgHooks['TitleExists'][$key] );
1508  $linkCache->clearLink( $title );
1509  } );
1510  }
1511 }
1512 
User\getDefaultOption
static getDefaultOption( $opt)
Get a given default option value.
Definition: User.php:1524
ParserOptions\setMaxIncludeSize
setMaxIncludeSize( $x)
Maximum size of template expansions, in bytes.
Definition: ParserOptions.php:355
ParserOptions\getMagicPMIDLinks
getMagicPMIDLinks()
Are magic PMID links enabled?
Definition: ParserOptions.php:718
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:766
ParserOptions\getExpensiveParserFunctionLimit
getExpensiveParserFunctionLimit()
Maximum number of calls per parse to expensive parser functions.
Definition: ParserOptions.php:406
ParserOptions\setTidy
setTidy( $x)
Use tidy to cleanup output HTML?
Definition: ParserOptions.php:302
ParserOptions\getIsSectionPreview
getIsSectionPreview()
Parsing the page for a "preview" operation on a single section?
Definition: ParserOptions.php:581
$wgMaxArticleSize
$wgMaxArticleSize
Maximum article size in kilobytes.
Definition: DefaultSettings.php:2399
ParserOptions\getRemoveComments
getRemoveComments()
Remove HTML comments.
Definition: ParserOptions.php:425
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:757
ParserOptions\disableContentConversion
disableContentConversion( $x=true)
Whether content conversion should be disabled.
Definition: ParserOptions.php:505
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:163
$lang
if(!isset( $args[0])) $lang
Definition: testCompression.php:37
ParserOptions\initialiseFromUser
initialiseFromUser( $user, $lang)
Get user options.
Definition: ParserOptions.php:1244
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:1550
$wgMaxTemplateDepth
$wgMaxTemplateDepth
Maximum recursion depth for templates within templates.
Definition: DefaultSettings.php:4565
ParserOptions\getIsPreview
getIsPreview()
Parsing the page for a "preview" operation?
Definition: ParserOptions.php:564
ParserOptions\getDisableTitleConversion
getDisableTitleConversion()
Whether title conversion should be disabled.
Definition: ParserOptions.php:513
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:889
ParserOptions\setIsPreview
setIsPreview( $x)
Parsing the page for a "preview" operation?
Definition: ParserOptions.php:573
ParserOptions\setTargetLanguage
setTargetLanguage( $x)
Target language for the parse.
Definition: ParserOptions.php:338
ParserOptions\getInterfaceMessage
getInterfaceMessage()
Parsing an interface message?
Definition: ParserOptions.php:312
ParserOptions\setIsSectionPreview
setIsSectionPreview( $x)
Parsing the page for a "preview" operation on a single section?
Definition: ParserOptions.php:590
ParserOptions\getSpeculativeRevId
getSpeculativeRevId()
A guess for {{REVISIONID}}, calculated using the callback provided via setSpeculativeRevIdCallback().
Definition: ParserOptions.php:903
ParserOptions\newFromAnon
static newFromAnon()
Get a ParserOptions object for an anonymous user.
Definition: ParserOptions.php:1063
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:3257
ParserOptions\setWrapOutputClass
setWrapOutputClass( $className)
CSS class to use to wrap output from Parser::parse()
Definition: ParserOptions.php:777
ParserOptions\setSpeculativeRevIdCallback
setSpeculativeRevIdCallback( $x)
Callback to generate a guess for {{REVISIONID}}.
Definition: ParserOptions.php:955
ParserOptions\disableTitleConversion
disableTitleConversion( $x=true)
Whether title conversion should be disabled.
Definition: ParserOptions.php:522
ParserOptions\initDateFormat
static initDateFormat(ParserOptions $popt)
Lazy initializer for dateFormat.
Definition: ParserOptions.php:641
ParserOptions\getIsPrintable
getIsPrintable()
Parsing the printable version of the page?
Definition: ParserOptions.php:598
ParserOptions\setCurrentRevisionCallback
setCurrentRevisionCallback( $x)
Callback for current revision fetching; first argument to call_user_func().
Definition: ParserOptions.php:860
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:397
ParserOptions\getMagicRFCLinks
getMagicRFCLinks()
Are magic RFC links enabled?
Definition: ParserOptions.php:727
ParserOptions\getUserLangObj
getUserLangObj()
Get the user language used by the parser for this page and split the parser cache.
Definition: ParserOptions.php:671
ParserOptions\registerWatcher
registerWatcher( $callback)
Registers a callback for tracking which ParserOptions which are used.
Definition: ParserOptions.php:1326
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:1475
ParserOptions\getDateFormat
getDateFormat()
Date format index.
Definition: ParserOptions.php:632
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:927
ParserOptions\setNumberHeadings
setNumberHeadings( $x)
Automatically number headings?
Definition: ParserOptions.php:275
$wgHooks
$wgHooks
Global list of hooks.
Definition: DefaultSettings.php:7939
ParserOptions\getCanonicalOverrides
static getCanonicalOverrides()
Get "canonical" non-default option values.
Definition: ParserOptions.php:1230
wfDeprecated
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that $function is deprecated.
Definition: GlobalFunctions.php:1027
ParserOptions\getRedirectTarget
getRedirectTarget()
Get the previously-set redirect target.
Definition: ParserOptions.php:1011
ParserOptions\newFromUserAndLang
static newFromUserAndLang(User $user, Language $lang)
Get a ParserOptions object from a given user and language.
Definition: ParserOptions.php:1090
ParserOptions\setUserLang
setUserLang( $x)
Set the user language used by the parser for this page and split the parser cache.
Definition: ParserOptions.php:696
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:4611
ParserOptions\getMaxIncludeSize
getMaxIncludeSize()
Maximum size of template expansions, in bytes.
Definition: ParserOptions.php:346
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:539
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:3125
ParserOptions\setExternalLinkTarget
setExternalLinkTarget( $x)
Target attribute for external links.
Definition: ParserOptions.php:488
ParserOptions\setDateFormat
setDateFormat( $x)
Date format index.
Definition: ParserOptions.php:650
ParserOptions\getTargetLanguage
getTargetLanguage()
Target language for the parse.
Definition: ParserOptions.php:329
$title
$title
Definition: testCompression.php:38
ParserOptions\initSpeculativePageId
static initSpeculativePageId(ParserOptions $popt)
Callback registered with ParserOptions::$lazyOptions, triggered by getSpeculativePageId().
Definition: ParserOptions.php:941
ParserOptions\setAllowSpecialInclusion
setAllowSpecialInclusion( $x)
Allow inclusion of special pages?
Definition: ParserOptions.php:292
$wgMaxPPExpandDepth
$wgMaxPPExpandDepth
Definition: DefaultSettings.php:4570
ParserOptions\getDefaults
static getDefaults()
Get default option values.
Definition: ParserOptions.php:1155
ParserOptions\getExternalLinkTarget
getExternalLinkTarget()
Target attribute for external links.
Definition: ParserOptions.php:479
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:1844
ParserOptions\getStubThreshold
getStubThreshold()
Thumb size preferred by the user.
Definition: ParserOptions.php:547
$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:687
$wgDisableLangConversion
$wgDisableLangConversion
Whether to enable language variant conversion.
Definition: DefaultSettings.php:3252
ParserOptions\getPreSaveTransform
getPreSaveTransform()
Transform wiki markup when saving the page?
Definition: ParserOptions.php:615
ParserOptions\setStubThreshold
setStubThreshold( $x)
Thumb size preferred by the user.
Definition: ParserOptions.php:556
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:745
ParserOptions\getDisableContentConversion
getDisableContentConversion()
Whether content conversion should be disabled.
Definition: ParserOptions.php:496
ParserOptions\optionToString
optionToString( $value)
Convert an option to a string value.
Definition: ParserOptions.php:1363
ParserOptions\matchesForCacheKey
matchesForCacheKey(ParserOptions $other)
Definition: ParserOptions.php:1305
ParserOptions\optionUsed
optionUsed( $optionName)
Called when an option is accessed.
Definition: ParserOptions.php:1338
$content
$content
Definition: router.php:76
ParserOptions\getSpeculativePageId
getSpeculativePageId()
A guess for {{PAGEID}}, calculated using the callback provided via setSpeculativeRevPageCallback().
Definition: ParserOptions.php:917
ParserOptions\setTimestamp
setTimestamp( $x)
Timestamp used for {{CURRENTDAY}} etc.
Definition: ParserOptions.php:987
ParserOptions\setSpeculativePageIdCallback
setSpeculativePageIdCallback( $x)
Callback to generate a guess for {{PAGEID}}.
Definition: ParserOptions.php:966
ParserOptions\setCleanSignatures
setCleanSignatures( $x)
Clean up signature texts?
Definition: ParserOptions.php:471
ParserOptions\newFromContext
static newFromContext(IContextSource $context)
Get a ParserOptions object from a IContextSource object.
Definition: ParserOptions.php:1102
Revision\MutableRevisionRecord
Definition: MutableRevisionRecord.php:45
ParserOptions\getCurrentRevisionCallback
getCurrentRevisionCallback()
Callback for current revision fetching; first argument to call_user_func().
Definition: ParserOptions.php:793
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:7795
ParserOptions\getTemplateCallback
getTemplateCallback()
Callback for template fetching; first argument to call_user_func().
Definition: ParserOptions.php:880
ParserOptions\newCanonical
static newCanonical( $context=null, $userLang=null)
Creates a "canonical" ParserOptions object.
Definition: ParserOptions.php:1124
ParserOptions\setRemoveComments
setRemoveComments( $x)
Remove HTML comments.
Definition: ParserOptions.php:435
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:1001
ParserOptions\setExpensiveParserFunctionLimit
setExpensiveParserFunctionLimit( $x)
Maximum number of calls per parse to expensive parser functions.
Definition: ParserOptions.php:416
ParserOptions\getTimestamp
getTimestamp()
Timestamp used for {{CURRENTDAY}} etc.
Definition: ParserOptions.php:975
ParserOptions\setMaxPPNodeCount
setMaxPPNodeCount( $x)
Maximum number of nodes touched by PPFrame::expand()
Definition: ParserOptions.php:372
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:461
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:1263
ParserOptions\enableLimitReport
enableLimitReport( $x=true)
Enable limit report in an HTML comment on output.
Definition: ParserOptions.php:452
Title
Represents a title within MediaWiki.
Definition: Title.php:41
ParserOptions\__construct
__construct( $user=null, $lang=null)
Definition: ParserOptions.php:1039
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:321
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:1349
$wgCleanSignatures
$wgCleanSignatures
If true, removes (by substituting) templates in signatures.
Definition: DefaultSettings.php:4592
ParserOptions\getUser
getUser()
Current user.
Definition: ParserOptions.php:1029
ParserOptions\getThumbSize
getThumbSize()
Thumb size preferred by the user.
Definition: ParserOptions.php:530
ParserOptions\getMagicISBNLinks
getMagicISBNLinks()
Are magic ISBN links enabled?
Definition: ParserOptions.php:709
ParserOptions\setIsPrintable
setIsPrintable( $x)
Parsing the printable version of the page?
Definition: ParserOptions.php:607
ParserOptions\getMaxPPNodeCount
getMaxPPNodeCount()
Maximum number of nodes touched by PPFrame::expand()
Definition: ParserOptions.php:363
$wgRenderHashAppend
$wgRenderHashAppend
Append a configured value to the parser cache and the sitenotice key so that they can be kept separat...
Definition: DefaultSettings.php:2805
ParserOptions\getCurrentRevisionRecordCallback
getCurrentRevisionRecordCallback()
Callback for current revision fetching; first argument to call_user_func().
Definition: ParserOptions.php:831
ParserOptions\getMaxPPExpandDepth
getMaxPPExpandDepth()
Maximum recursion depth in PPFrame::expand()
Definition: ParserOptions.php:380
ParserOptions\getEnableLimitReport
getEnableLimitReport()
Enable limit report in an HTML comment on output.
Definition: ParserOptions.php:443
ParserOptions\getNumberHeadings
getNumberHeadings()
Automatically number headings?
Definition: ParserOptions.php:266
ParserOptions\isSafeToCache
isSafeToCache()
Test whether these options are safe to cache.
Definition: ParserOptions.php:1451
ParserOptions\getMaxTemplateDepth
getMaxTemplateDepth()
Maximum recursion depth for templates within templates.
Definition: ParserOptions.php:388
ParserOptions\setPreSaveTransform
setPreSaveTransform( $x)
Transform wiki markup when saving the page?
Definition: ParserOptions.php:624
User
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition: User.php:56
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:4557
ParserOptions\setCurrentRevisionRecordCallback
setCurrentRevisionRecordCallback( $x)
Callback for current revision fetching; first argument to call_user_func().
Definition: ParserOptions.php:872
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:1391
IContextSource\getLanguage
getLanguage()
Revision\SlotRecord
Value object representing a content slot associated with a page revision.
Definition: SlotRecord.php:40
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:1077
$wgAllowExternalImages
$wgAllowExternalImages
Whether to allow inline image pointing to other websites.
Definition: DefaultSettings.php:4597
$wgEnableImageWhitelist
$wgEnableImageWhitelist
If $wgAllowExternalImages is false, you can allow an on-wiki allow list of regular expression fragmen...
Definition: DefaultSettings.php:4624
ParserOptions\addExtraKey
addExtraKey( $key)
Extra key that should be present in the parser cache key.
Definition: ParserOptions.php:1021
$wgAllowSpecialInclusion
$wgAllowSpecialInclusion
Allow special page inclusions such as {{Special:Allpages}}.
Definition: DefaultSettings.php:8381