MediaWiki  master
ParserOptions.php
Go to the documentation of this file.
1 <?php
25 use Wikimedia\ScopedCallback;
26 
43 
49  private static $defaults = null;
50 
55  private static $lazyOptions = [
56  'dateformat' => [ __CLASS__, 'initDateFormat' ],
57  'speculativeRevId' => [ __CLASS__, 'initSpeculativeRevId' ],
58  'speculativePageId' => [ __CLASS__, 'initSpeculativePageId' ],
59  ];
60 
65  private static $inCacheKey = [
66  'dateformat' => true,
67  'numberheadings' => true,
68  'thumbsize' => true,
69  'stubthreshold' => true,
70  'printable' => true,
71  'userlang' => true,
72  ];
73 
78  private $options;
79 
85  private $mTimestamp;
86 
92  private $mUser;
93 
99  private $onAccessCallback = null;
100 
107  private $redirectTarget = null;
108 
112  private $mExtraKey = '';
113 
120  public function getOption( $name ) {
121  if ( !array_key_exists( $name, $this->options ) ) {
122  throw new InvalidArgumentException( "Unknown parser option $name" );
123  }
124 
125  $this->lazyLoadOption( $name );
126  if ( !empty( self::$inCacheKey[$name] ) ) {
127  $this->optionUsed( $name );
128  }
129  return $this->options[$name];
130  }
131 
135  private function lazyLoadOption( $name ) {
136  if ( isset( self::$lazyOptions[$name] ) && $this->options[$name] === null ) {
137  $this->options[$name] = call_user_func( self::$lazyOptions[$name], $this, $name );
138  }
139  }
140 
149  public function setOption( $name, $value ) {
150  if ( !array_key_exists( $name, $this->options ) ) {
151  throw new InvalidArgumentException( "Unknown parser option $name" );
152  }
153  $old = $this->options[$name];
154  $this->options[$name] = $value;
155  return $old;
156  }
157 
166  protected function setOptionLegacy( $name, $value ) {
167  if ( !array_key_exists( $name, $this->options ) ) {
168  throw new InvalidArgumentException( "Unknown parser option $name" );
169  }
170  return wfSetVar( $this->options[$name], $value );
171  }
172 
181  public function getInterwikiMagic() {
182  return $this->getOption( 'interwikiMagic' );
183  }
184 
190  public function setInterwikiMagic( $x ) {
191  return $this->setOptionLegacy( 'interwikiMagic', $x );
192  }
193 
198  public function getAllowExternalImages() {
199  return $this->getOption( 'allowExternalImages' );
200  }
201 
207  public function setAllowExternalImages( $x ) {
208  return $this->setOptionLegacy( 'allowExternalImages', $x );
209  }
210 
218  public function getAllowExternalImagesFrom() {
219  return $this->getOption( 'allowExternalImagesFrom' );
220  }
221 
230  public function setAllowExternalImagesFrom( $x ) {
231  return $this->setOptionLegacy( 'allowExternalImagesFrom', $x );
232  }
233 
238  public function getEnableImageWhitelist() {
239  return $this->getOption( 'enableImageWhitelist' );
240  }
241 
247  public function setEnableImageWhitelist( $x ) {
248  return $this->setOptionLegacy( 'enableImageWhitelist', $x );
249  }
250 
255  public function getNumberHeadings() {
256  return $this->getOption( 'numberheadings' );
257  }
258 
264  public function setNumberHeadings( $x ) {
265  return $this->setOptionLegacy( 'numberheadings', $x );
266  }
267 
272  public function getAllowSpecialInclusion() {
273  return $this->getOption( 'allowSpecialInclusion' );
274  }
275 
281  public function setAllowSpecialInclusion( $x ) {
282  return $this->setOptionLegacy( 'allowSpecialInclusion', $x );
283  }
284 
290  public function getTidy() {
291  wfDeprecated( __METHOD__, '1.35' );
292  return $this->getOption( 'tidy' );
293  }
294 
301  public function setTidy( $x ) {
302  if ( !$x ) {
303  wfDeprecated( 'disabling tidy', '1.33' );
304  }
305  return $this->setOptionLegacy( 'tidy', $x );
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  $revCb = $this->getOption( 'currentRevisionCallback' );
795 
796  // As a temporary measure, while both currentRevisionCallback and
797  // currentRevisionRecordCallback are supported, retrieving one that is
798  // not set first checks if the other is set, so that the end result works
799  // regardless of which setter was used, since one extension may set a
800  // RevisionCallback and another may ask for the RevisionRecordCallback
801  if ( $revCb === [ Parser::class, 'statelessFetchRevision' ] ) {
802  // currentRevisionCallback is set to the default, check if
803  // currentRevisionRecordCallback is set (and not the default)
804  $revRecordCb = $this->getOption( 'currentRevisionRecordCallback' );
805  if ( $revRecordCb !== [ Parser::class, 'statelessFetchRevisionRecord' ] ) {
806  // currentRevisionRecordCallback is set and not the default,
807  // convert it
808  $revCb = function ( Title $title, $parser = false ) use ( $revRecordCb ) {
809  $revRecord = call_user_func(
810  $revRecordCb,
811  $title,
812  $parser ?: null
813  );
814  if ( $revRecord ) {
815  return new Revision( $revRecord );
816  }
817  return false;
818  };
819  }
820  }
821  return $revCb;
822  }
823 
831  $revRecordCb = $this->getOption( 'currentRevisionRecordCallback' );
832 
833  // See explanation above
834  if ( $revRecordCb === [ Parser::class, 'statelessFetchRevisionRecord' ] ) {
835  // currentRevisionRecordCallback is set to the default, check if
836  // currentRevisionCallback is set (and not the default)
837  $revCb = $this->getOption( 'currentRevisionCallback' );
838  if ( $revCb !== [ Parser::class, 'statelessFetchRevision' ] ) {
839  // currentRevisionCallback is set and not the default, convert it
840  $revRecordCb = function ( Title $title, $parser = null ) use ( $revCb ) {
841  $rev = call_user_func( $revCb, $title, $parser ?? false );
842  if ( $rev ) {
843  return $rev->getRevisionRecord();
844  }
845  return false;
846  };
847  }
848  }
849  return $revRecordCb;
850  }
851 
859  public function setCurrentRevisionCallback( $x ) {
860  return $this->setOptionLegacy( 'currentRevisionCallback', $x );
861  }
862 
870  public function setCurrentRevisionRecordCallback( $x ) {
871  return $this->setOption( 'currentRevisionRecordCallback', $x );
872  }
873 
878  public function getTemplateCallback() {
879  return $this->getOption( 'templateCallback' );
880  }
881 
887  public function setTemplateCallback( $x ) {
888  return $this->setOptionLegacy( 'templateCallback', $x );
889  }
890 
901  public function getSpeculativeRevId() {
902  return $this->getOption( 'speculativeRevId' );
903  }
904 
915  public function getSpeculativePageId() {
916  return $this->getOption( 'speculativePageId' );
917  }
918 
925  private static function initSpeculativeRevId( ParserOptions $popt ) {
926  $cb = $popt->getOption( 'speculativeRevIdCallback' );
927  $id = $cb ? $cb() : null;
928 
929  // returning null would result in this being re-called every access
930  return $id ?? false;
931  }
932 
939  private static function initSpeculativePageId( ParserOptions $popt ) {
940  $cb = $popt->getOption( 'speculativePageIdCallback' );
941  $id = $cb ? $cb() : null;
942 
943  // returning null would result in this being re-called every access
944  return $id ?? false;
945  }
946 
953  public function setSpeculativeRevIdCallback( $x ) {
954  $this->setOption( 'speculativeRevId', null ); // reset
955  return $this->setOption( 'speculativeRevIdCallback', $x );
956  }
957 
964  public function setSpeculativePageIdCallback( $x ) {
965  $this->setOption( 'speculativePageId', null ); // reset
966  return $this->setOption( 'speculativePageIdCallback', $x );
967  }
968 
973  public function getTimestamp() {
974  if ( !isset( $this->mTimestamp ) ) {
975  $this->mTimestamp = wfTimestampNow();
976  }
977  return $this->mTimestamp;
978  }
979 
985  public function setTimestamp( $x ) {
986  return wfSetVar( $this->mTimestamp, $x );
987  }
988 
999  public function setRedirectTarget( $title ) {
1000  $this->redirectTarget = $title;
1001  }
1002 
1009  public function getRedirectTarget() {
1010  return $this->redirectTarget;
1011  }
1012 
1019  public function addExtraKey( $key ) {
1020  $this->mExtraKey .= '!' . $key;
1021  }
1022 
1027  public function getUser() {
1028  return $this->mUser;
1029  }
1030 
1037  public function __construct( $user = null, $lang = null ) {
1038  if ( $user === null ) {
1039  global $wgUser;
1040  if ( $wgUser === null ) {
1041  $user = new User;
1042  } else {
1043  $user = $wgUser;
1044  }
1045  }
1046  if ( $lang === null ) {
1047  global $wgLang;
1048  if ( !StubObject::isRealObject( $wgLang ) ) {
1049  $wgLang->_unstub();
1050  }
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 
1123  public static function newCanonical( $context = null, $userLang = null ) {
1124  if ( $context instanceof IContextSource ) {
1125  $ret = self::newFromContext( $context );
1126  } elseif ( $context === 'canonical' ) {
1127  $ret = self::newFromAnon();
1128  } elseif ( $context instanceof User || $context === null ) {
1129  $ret = new self( $context, $userLang );
1130  } else {
1131  throw new InvalidArgumentException(
1132  '$context must be an IContextSource, the string "canonical", a User, or null'
1133  );
1134  }
1135 
1136  foreach ( self::getCanonicalOverrides() as $k => $v ) {
1137  $ret->setOption( $k, $v );
1138  }
1139  return $ret;
1140  }
1141 
1151  private static function getDefaults() {
1158 
1159  if ( self::$defaults === null ) {
1160  // *UPDATE* ParserOptions::matches() if any of this changes as needed
1161  self::$defaults = [
1162  'dateformat' => null,
1163  'tidy' => true,
1164  'interfaceMessage' => false,
1165  'targetLanguage' => null,
1166  'removeComments' => true,
1167  'enableLimitReport' => false,
1168  'preSaveTransform' => true,
1169  'isPreview' => false,
1170  'isSectionPreview' => false,
1171  'printable' => false,
1172  'allowUnsafeRawHtml' => true,
1173  'wrapclass' => 'mw-parser-output',
1174  'currentRevisionCallback' => [ Parser::class, 'statelessFetchRevision' ],
1175  'currentRevisionRecordCallback' => [ Parser::class, 'statelessFetchRevisionRecord' ],
1176  'templateCallback' => [ Parser::class, 'statelessFetchTemplate' ],
1177  'speculativeRevIdCallback' => null,
1178  'speculativeRevId' => null,
1179  'speculativePageIdCallback' => null,
1180  'speculativePageId' => null,
1181  ];
1182 
1183  Hooks::run( 'ParserOptionsRegister', [
1184  &self::$defaults,
1185  &self::$inCacheKey,
1186  &self::$lazyOptions,
1187  ] );
1188 
1189  ksort( self::$inCacheKey );
1190  }
1191 
1192  // Unit tests depend on being able to modify the globals at will
1193  return self::$defaults + [
1194  'interwikiMagic' => $wgInterwikiMagic,
1195  'allowExternalImages' => $wgAllowExternalImages,
1196  'allowExternalImagesFrom' => $wgAllowExternalImagesFrom,
1197  'enableImageWhitelist' => $wgEnableImageWhitelist,
1198  'allowSpecialInclusion' => $wgAllowSpecialInclusion,
1199  'maxIncludeSize' => $wgMaxArticleSize * 1024,
1200  'maxPPNodeCount' => $wgMaxPPNodeCount,
1201  'maxPPExpandDepth' => $wgMaxPPExpandDepth,
1202  'maxTemplateDepth' => $wgMaxTemplateDepth,
1203  'expensiveParserFunctionLimit' => $wgExpensiveParserFunctionLimit,
1204  'externalLinkTarget' => $wgExternalLinkTarget,
1205  'cleanSignatures' => $wgCleanSignatures,
1206  'disableContentConversion' => $wgDisableLangConversion,
1207  'disableTitleConversion' => $wgDisableLangConversion || $wgDisableTitleConversion,
1208  'magicISBNLinks' => $wgEnableMagicLinks['ISBN'],
1209  'magicPMIDLinks' => $wgEnableMagicLinks['PMID'],
1210  'magicRFCLinks' => $wgEnableMagicLinks['RFC'],
1211  'numberheadings' => User::getDefaultOption( 'numberheadings' ),
1212  'thumbsize' => User::getDefaultOption( 'thumbsize' ),
1213  'stubthreshold' => 0,
1214  'userlang' => MediaWikiServices::getInstance()->getContentLanguage(),
1215  ];
1216  }
1217 
1227  private static function getCanonicalOverrides() {
1229 
1230  return [
1231  'enableLimitReport' => $wgEnableParserLimitReporting,
1232  ];
1233  }
1234 
1241  private function initialiseFromUser( $user, $lang ) {
1242  $this->options = self::getDefaults();
1243 
1244  $this->mUser = $user;
1245  $this->options['numberheadings'] = $user->getOption( 'numberheadings' );
1246  $this->options['thumbsize'] = $user->getOption( 'thumbsize' );
1247  $this->options['stubthreshold'] = $user->getStubThreshold();
1248  $this->options['userlang'] = $lang;
1249  }
1250 
1260  public function matches( ParserOptions $other ) {
1261  // Compare most options
1262  $options = array_keys( $this->options );
1263  $options = array_diff( $options, [
1264  'enableLimitReport', // only affects HTML comments
1265  ] );
1266  foreach ( $options as $option ) {
1267  // Resolve any lazy options
1268  $this->lazyLoadOption( $option );
1269  $other->lazyLoadOption( $option );
1270 
1271  $o1 = $this->optionToString( $this->options[$option] );
1272  $o2 = $this->optionToString( $other->options[$option] );
1273  if ( $o1 !== $o2 ) {
1274  return false;
1275  }
1276  }
1277 
1278  // Compare most other fields
1279  $fields = array_keys( get_class_vars( __CLASS__ ) );
1280  $fields = array_diff( $fields, [
1281  'defaults', // static
1282  'lazyOptions', // static
1283  'inCacheKey', // static
1284  'options', // Already checked above
1285  'onAccessCallback', // only used for ParserOutput option tracking
1286  ] );
1287  foreach ( $fields as $field ) {
1288  if ( !is_object( $this->$field ) && $this->$field !== $other->$field ) {
1289  return false;
1290  }
1291  }
1292 
1293  return true;
1294  }
1295 
1301  public function matchesForCacheKey( ParserOptions $other ) {
1302  foreach ( self::allCacheVaryingOptions() as $option ) {
1303  // Populate any lazy options
1304  $this->lazyLoadOption( $option );
1305  $other->lazyLoadOption( $option );
1306 
1307  $o1 = $this->optionToString( $this->options[$option] );
1308  $o2 = $this->optionToString( $other->options[$option] );
1309  if ( $o1 !== $o2 ) {
1310  return false;
1311  }
1312  }
1313 
1314  return true;
1315  }
1316 
1322  public function registerWatcher( $callback ) {
1323  $this->onAccessCallback = $callback;
1324  }
1325 
1334  public function optionUsed( $optionName ) {
1335  if ( $this->onAccessCallback ) {
1336  call_user_func( $this->onAccessCallback, $optionName );
1337  }
1338  }
1339 
1345  public static function allCacheVaryingOptions() {
1346  // Trigger a call to the 'ParserOptionsRegister' hook if it hasn't
1347  // already been called.
1348  if ( self::$defaults === null ) {
1350  }
1351  return array_keys( array_filter( self::$inCacheKey ) );
1352  }
1353 
1359  private function optionToString( $value ) {
1360  if ( $value === true ) {
1361  return '1';
1362  } elseif ( $value === false ) {
1363  return '0';
1364  } elseif ( $value === null ) {
1365  return '';
1366  } elseif ( $value instanceof Language ) {
1367  return $value->getCode();
1368  } elseif ( is_array( $value ) ) {
1369  return '[' . implode( ',', array_map( [ $this, 'optionToString' ], $value ) ) . ']';
1370  } else {
1371  return (string)$value;
1372  }
1373  }
1374 
1387  public function optionsHash( $forOptions, $title = null ) {
1388  global $wgRenderHashAppend;
1389 
1391 
1392  // Resolve any lazy options
1393  $lazyOpts = array_intersect( $forOptions, $inCacheKey, array_keys( self::$lazyOptions ) );
1394  foreach ( $lazyOpts as $k ) {
1395  $this->lazyLoadOption( $k );
1396  }
1397 
1400 
1401  // We only include used options with non-canonical values in the key
1402  // so adding a new option doesn't invalidate the entire parser cache.
1403  // The drawback to this is that changing the default value of an option
1404  // requires manual invalidation of existing cache entries, as mentioned
1405  // in the docs on the relevant methods and hooks.
1406  $values = [];
1407  foreach ( array_intersect( $inCacheKey, $forOptions ) as $option ) {
1408  $v = $this->optionToString( $options[$option] );
1409  $d = $this->optionToString( $defaults[$option] );
1410  if ( $v !== $d ) {
1411  $values[] = "$option=$v";
1412  }
1413  }
1414 
1415  $confstr = $values ? implode( '!', $values ) : 'canonical';
1416 
1417  // add in language specific options, if any
1418  // @todo FIXME: This is just a way of retrieving the url/user preferred variant
1419 
1420  $lang = $title ? $title->getPageLanguage() :
1421  MediaWikiServices::getInstance()->getContentLanguage();
1422  $converter = MediaWikiServices::getInstance()->getLanguageConverterFactory()
1423  ->getLanguageConverter( $lang );
1424  $confstr .= $converter->getExtraHashOptions();
1425 
1426  $confstr .= $wgRenderHashAppend;
1427 
1428  if ( $this->mExtraKey != '' ) {
1429  $confstr .= $this->mExtraKey;
1430  }
1431 
1432  // Give a chance for extensions to modify the hash, if they have
1433  // extra options or other effects on the parser cache.
1434  Hooks::run( 'PageRenderingHash', [ &$confstr, $this->getUser(), &$forOptions ] );
1435 
1436  // Make it a valid memcached key fragment
1437  $confstr = str_replace( ' ', '_', $confstr );
1438 
1439  return $confstr;
1440  }
1441 
1447  public function isSafeToCache() {
1449  foreach ( $this->options as $option => $value ) {
1450  if ( empty( self::$inCacheKey[$option] ) ) {
1451  $v = $this->optionToString( $value );
1452  $d = $this->optionToString( $defaults[$option] );
1453  if ( $v !== $d ) {
1454  return false;
1455  }
1456  }
1457  }
1458  return true;
1459  }
1460 
1471  public function setupFakeRevision( $title, $content, $user ) {
1472  $oldCallback = $this->setCurrentRevisionCallback(
1473  function (
1474  $titleToCheck, $parser = false ) use ( $title, $content, $user, &$oldCallback
1475  ) {
1476  if ( $titleToCheck->equals( $title ) ) {
1477  return new Revision( [
1478  'page' => $title->getArticleID(),
1479  'user_text' => $user->getName(),
1480  'user' => $user->getId(),
1481  'parent_id' => $title->getLatestRevID(),
1482  'title' => $title,
1483  'content' => $content
1484  ] );
1485  } else {
1486  return call_user_func( $oldCallback, $titleToCheck, $parser );
1487  }
1488  }
1489  );
1490 
1491  global $wgHooks;
1492  $wgHooks['TitleExists'][] =
1493  function ( $titleToCheck, &$exists ) use ( $title ) {
1494  if ( $titleToCheck->equals( $title ) ) {
1495  $exists = true;
1496  }
1497  };
1498  end( $wgHooks['TitleExists'] );
1499  $key = key( $wgHooks['TitleExists'] );
1500  $linkCache = MediaWikiServices::getInstance()->getLinkCache();
1501  $linkCache->clearBadLink( $title->getPrefixedDBkey() );
1502  return new ScopedCallback( function () use ( $title, $key, $linkCache ) {
1503  global $wgHooks;
1504  unset( $wgHooks['TitleExists'][$key] );
1505  $linkCache->clearLink( $title );
1506  } );
1507  }
1508 }
1509 
User\getDefaultOption
static getDefaultOption( $opt)
Get a given default option value.
Definition: User.php:1608
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:42
ParserOptions\setOptionLegacy
setOptionLegacy( $name, $value)
Legacy implementation.
Definition: ParserOptions.php:166
ParserOptions\getAllowExternalImagesFrom
getAllowExternalImagesFrom()
External images to allow.
Definition: ParserOptions.php:218
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:301
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:2377
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:144
$lang
if(!isset( $args[0])) $lang
Definition: testCompression.php:37
ParserOptions\initialiseFromUser
initialiseFromUser( $user, $lang)
Get user options.
Definition: ParserOptions.php:1241
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:1541
$wgMaxTemplateDepth
$wgMaxTemplateDepth
Maximum recursion depth for templates within templates.
Definition: DefaultSettings.php:4526
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:207
ParserOptions\setTemplateCallback
setTemplateCallback( $x)
Callback for template fetching; first argument to call_user_func().
Definition: ParserOptions.php:887
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:901
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:247
$wgDisableTitleConversion
$wgDisableTitleConversion
Whether to enable language variant conversion for links.
Definition: DefaultSettings.php:3218
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:953
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:859
ParserOptions\$inCacheKey
static array $inCacheKey
Specify options that are included in the cache key.
Definition: ParserOptions.php:65
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:1322
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:1471
ParserOptions\getDateFormat
getDateFormat()
Date format index.
Definition: ParserOptions.php:632
Revision
Definition: Revision.php:39
ParserOptions\setOption
setOption( $name, $value)
Set an option, generically.
Definition: ParserOptions.php:149
ParserOptions\initSpeculativeRevId
static initSpeculativeRevId(ParserOptions $popt)
Callback registered with ParserOptions::$lazyOptions, triggered by getSpeculativeRevId().
Definition: ParserOptions.php:925
ParserOptions\setNumberHeadings
setNumberHeadings( $x)
Automatically number headings?
Definition: ParserOptions.php:264
$wgHooks
$wgHooks
Global list of hooks.
Definition: DefaultSettings.php:7856
ParserOptions\getCanonicalOverrides
static getCanonicalOverrides()
Get "canonical" non-default option values.
Definition: ParserOptions.php:1227
wfDeprecated
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that $function is deprecated.
Definition: GlobalFunctions.php:1030
ParserOptions\getRedirectTarget
getRedirectTarget()
Get the previously-set redirect target.
Definition: ParserOptions.php:1009
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:272
$wgAllowExternalImagesFrom
$wgAllowExternalImagesFrom
If the above is false, you can specify an exception here.
Definition: DefaultSettings.php:4572
ParserOptions\getTidy
getTidy()
Use tidy to cleanup output HTML?
Definition: ParserOptions.php:290
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:85
$wgLang
$wgLang
Definition: Setup.php:774
$wgExpensiveParserFunctionLimit
$wgExpensiveParserFunctionLimit
Maximum number of calls per parse to expensive parser functions such as PAGESINCATEGORY.
Definition: DefaultSettings.php:4681
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:238
$wgInterwikiMagic
$wgInterwikiMagic
Treat language links as magic connectors, not inline links.
Definition: DefaultSettings.php:3086
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:939
ParserOptions\setAllowSpecialInclusion
setAllowSpecialInclusion( $x)
Allow inclusion of special pages?
Definition: ParserOptions.php:281
$wgMaxPPExpandDepth
$wgMaxPPExpandDepth
Definition: DefaultSettings.php:4531
ParserOptions\getDefaults
static getDefaults()
Get default option values.
Definition: ParserOptions.php:1151
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:99
$wgEnableMagicLinks
$wgEnableMagicLinks
Enable the magic links feature of automatically turning ISBN xxx, PMID xxx, RFC xxx into links.
Definition: DefaultSettings.php:4706
wfTimestampNow
wfTimestampNow()
Convenience function; returns MediaWiki timestamp for the present time.
Definition: GlobalFunctions.php:1835
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:4634
ParserOptions\$options
array $options
Current values for all options that are relevant for caching.
Definition: ParserOptions.php:78
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:3213
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:120
ParserOptions\$mExtraKey
$mExtraKey
Appended to the options hash.
Definition: ParserOptions.php:112
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:1359
ParserOptions\matchesForCacheKey
matchesForCacheKey(ParserOptions $other)
Definition: ParserOptions.php:1301
ParserOptions\optionUsed
optionUsed( $optionName)
Called when an option is accessed.
Definition: ParserOptions.php:1334
$content
$content
Definition: router.php:76
ParserOptions\getSpeculativePageId
getSpeculativePageId()
A guess for {{PAGEID}}, calculated using the callback provided via setSpeculativeRevPageCallback().
Definition: ParserOptions.php:915
ParserOptions\setTimestamp
setTimestamp( $x)
Timestamp used for {{CURRENTDAY}} etc.
Definition: ParserOptions.php:985
ParserOptions\setSpeculativePageIdCallback
setSpeculativePageIdCallback( $x)
Callback to generate a guess for {{PAGEID}}.
Definition: ParserOptions.php:964
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
ParserOptions\getCurrentRevisionCallback
getCurrentRevisionCallback()
Callback for current revision fetching; first argument to call_user_func().
Definition: ParserOptions.php:793
$wgEnableParserLimitReporting
$wgEnableParserLimitReporting
Whether to include the NewPP limit report as a HTML comment.
Definition: DefaultSettings.php:7712
ParserOptions\getTemplateCallback
getTemplateCallback()
Callback for template fetching; first argument to call_user_func().
Definition: ParserOptions.php:878
ParserOptions\newCanonical
static newCanonical( $context=null, $userLang=null)
Creates a "canonical" ParserOptions object.
Definition: ParserOptions.php:1123
ParserOptions\setRemoveComments
setRemoveComments( $x)
Remove HTML comments.
Definition: ParserOptions.php:435
ParserOptions\setInterwikiMagic
setInterwikiMagic( $x)
Specify whether to extract interlanguage links.
Definition: ParserOptions.php:190
ParserOptions\lazyLoadOption
lazyLoadOption( $name)
Definition: ParserOptions.php:135
ParserOptions\setRedirectTarget
setRedirectTarget( $title)
Set the redirect target.
Definition: ParserOptions.php:999
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:973
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:53
ParserOptions\getCleanSignatures
getCleanSignatures()
Clean up signature texts?
Definition: ParserOptions.php:461
$context
$context
Definition: load.php:43
ParserOptions\$redirectTarget
Title null $redirectTarget
If the page being parsed is a redirect, this should hold the redirect target.
Definition: ParserOptions.php:107
ParserOptions\setAllowExternalImagesFrom
setAllowExternalImagesFrom( $x)
External images to allow.
Definition: ParserOptions.php:230
ParserOptions\matches
matches(ParserOptions $other)
Check if these options match that of another options set.
Definition: ParserOptions.php:1260
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:42
ParserOptions\__construct
__construct( $user=null, $lang=null)
Definition: ParserOptions.php:1037
ParserOptions\getInterwikiMagic
getInterwikiMagic()
Whether to extract interlanguage links.
Definition: ParserOptions.php:181
ParserOptions\$lazyOptions
static callable[] $lazyOptions
Lazy-loaded options.
Definition: ParserOptions.php:55
ParserOptions\$mUser
User $mUser
Stored user object.
Definition: ParserOptions.php:92
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:49
ParserOptions\allCacheVaryingOptions
static allCacheVaryingOptions()
Return all option keys that vary the options hash.
Definition: ParserOptions.php:1345
$wgCleanSignatures
$wgCleanSignatures
If true, removes (by substituting) templates in signatures.
Definition: DefaultSettings.php:4553
ParserOptions\getUser
getUser()
Current user.
Definition: ParserOptions.php:1027
ParserOptions\getThumbSize
getThumbSize()
Thumb size preferred by the user.
Definition: ParserOptions.php:530
StubObject\isRealObject
static isRealObject( $obj)
Returns a bool value whenever $obj is a stub object.
Definition: StubObject.php:81
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:2774
ParserOptions\getCurrentRevisionRecordCallback
getCurrentRevisionRecordCallback()
Callback for current revision fetching; first argument to call_user_func().
Definition: ParserOptions.php:830
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:255
ParserOptions\isSafeToCache
isSafeToCache()
Test whether these options are safe to cache.
Definition: ParserOptions.php:1447
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:54
Hooks\run
static run( $event, array $args=[], $deprecatedVersion=null)
Call hook functions defined in Hooks::register and $wgHooks.
Definition: Hooks.php:133
$wgMaxPPNodeCount
$wgMaxPPNodeCount
A complexity limit on template expansion: the maximum number of nodes visited by PPFrame::expand()
Definition: DefaultSettings.php:4518
ParserOptions\setCurrentRevisionRecordCallback
setCurrentRevisionRecordCallback( $x)
Callback for current revision fetching; first argument to call_user_func().
Definition: ParserOptions.php:870
Language
Internationalisation code See https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation for more...
Definition: Language.php:39
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:1387
ParserOptions\getAllowExternalImages
getAllowExternalImages()
Allow all external images inline?
Definition: ParserOptions.php:198
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:4558
$wgEnableImageWhitelist
$wgEnableImageWhitelist
If $wgAllowExternalImages is false, you can allow an on-wiki whitelist of regular expression fragment...
Definition: DefaultSettings.php:4585
ParserOptions\addExtraKey
addExtraKey( $key)
Extra key that should be present in the parser cache key.
Definition: ParserOptions.php:1019
$wgAllowSpecialInclusion
$wgAllowSpecialInclusion
Allow special page inclusions such as {{Special:Allpages}}.
Definition: DefaultSettings.php:8295