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  'printable' => true,
72  'userlang' => true,
73  ];
74 
80  private static $callbacks = [
81  'currentRevisionCallback' => true,
82  'currentRevisionRecordCallback' => true,
83  'templateCallback' => true,
84  'speculativeRevIdCallback' => true,
85  'speculativePageIdCallback' => true,
86  ];
87 
92  private $options;
93 
99  private $mTimestamp;
100 
106  private $mUser;
107 
113  private $onAccessCallback = null;
114 
121  private $redirectTarget = null;
122 
126  private $mExtraKey = '';
127 
134  public function getOption( $name ) {
135  if ( !array_key_exists( $name, $this->options ) ) {
136  throw new InvalidArgumentException( "Unknown parser option $name" );
137  }
138 
139  $this->lazyLoadOption( $name );
140  $this->optionUsed( $name );
141  return $this->options[$name];
142  }
143 
147  private function lazyLoadOption( $name ) {
148  if ( isset( self::$lazyOptions[$name] ) && $this->options[$name] === null ) {
149  $this->options[$name] = call_user_func( self::$lazyOptions[$name], $this, $name );
150  }
151  }
152 
161  public function setOption( $name, $value ) {
162  if ( !array_key_exists( $name, $this->options ) ) {
163  throw new InvalidArgumentException( "Unknown parser option $name" );
164  }
165  $old = $this->options[$name];
166  $this->options[$name] = $value;
167  return $old;
168  }
169 
178  protected function setOptionLegacy( $name, $value ) {
179  if ( !array_key_exists( $name, $this->options ) ) {
180  throw new InvalidArgumentException( "Unknown parser option $name" );
181  }
182  return wfSetVar( $this->options[$name], $value );
183  }
184 
193  public function getInterwikiMagic() {
194  return $this->getOption( 'interwikiMagic' );
195  }
196 
202  public function setInterwikiMagic( $x ) {
203  return $this->setOptionLegacy( 'interwikiMagic', $x );
204  }
205 
210  public function getAllowExternalImages() {
211  return $this->getOption( 'allowExternalImages' );
212  }
213 
221  public function setAllowExternalImages( $x ) {
222  wfDeprecated( __METHOD__, '1.35' );
223  return $this->setOptionLegacy( 'allowExternalImages', $x );
224  }
225 
233  public function getAllowExternalImagesFrom() {
234  return $this->getOption( 'allowExternalImagesFrom' );
235  }
236 
247  public function setAllowExternalImagesFrom( $x ) {
248  wfDeprecated( __METHOD__, '1.35' );
249  return $this->setOptionLegacy( 'allowExternalImagesFrom', $x );
250  }
251 
256  public function getEnableImageWhitelist() {
257  return $this->getOption( 'enableImageWhitelist' );
258  }
259 
267  public function setEnableImageWhitelist( $x ) {
268  wfDeprecated( __METHOD__, '1.35' );
269  return $this->setOptionLegacy( 'enableImageWhitelist', $x );
270  }
271 
276  public function getNumberHeadings() {
277  return $this->getOption( 'numberheadings' );
278  }
279 
285  public function setNumberHeadings( $x ) {
286  return $this->setOptionLegacy( 'numberheadings', $x );
287  }
288 
293  public function getAllowSpecialInclusion() {
294  return $this->getOption( 'allowSpecialInclusion' );
295  }
296 
302  public function setAllowSpecialInclusion( $x ) {
303  return $this->setOptionLegacy( 'allowSpecialInclusion', $x );
304  }
305 
312  public function setTidy( $x ) {
313  wfDeprecated( __METHOD__, '1.35' );
314  // This has no effect.
315  return null;
316  }
317 
322  public function getInterfaceMessage() {
323  return $this->getOption( 'interfaceMessage' );
324  }
325 
331  public function setInterfaceMessage( $x ) {
332  return $this->setOptionLegacy( 'interfaceMessage', $x );
333  }
334 
339  public function getTargetLanguage() {
340  return $this->getOption( 'targetLanguage' );
341  }
342 
348  public function setTargetLanguage( $x ) {
349  return $this->setOption( 'targetLanguage', $x );
350  }
351 
356  public function getMaxIncludeSize() {
357  return $this->getOption( 'maxIncludeSize' );
358  }
359 
365  public function setMaxIncludeSize( $x ) {
366  return $this->setOptionLegacy( 'maxIncludeSize', $x );
367  }
368 
373  public function getMaxPPNodeCount() {
374  return $this->getOption( 'maxPPNodeCount' );
375  }
376 
382  public function setMaxPPNodeCount( $x ) {
383  return $this->setOptionLegacy( 'maxPPNodeCount', $x );
384  }
385 
390  public function getMaxPPExpandDepth() {
391  return $this->getOption( 'maxPPExpandDepth' );
392  }
393 
398  public function getMaxTemplateDepth() {
399  return $this->getOption( 'maxTemplateDepth' );
400  }
401 
407  public function setMaxTemplateDepth( $x ) {
408  return $this->setOptionLegacy( 'maxTemplateDepth', $x );
409  }
410 
417  return $this->getOption( 'expensiveParserFunctionLimit' );
418  }
419 
426  public function setExpensiveParserFunctionLimit( $x ) {
427  return $this->setOptionLegacy( 'expensiveParserFunctionLimit', $x );
428  }
429 
435  public function getRemoveComments() {
436  return $this->getOption( 'removeComments' );
437  }
438 
445  public function setRemoveComments( $x ) {
446  return $this->setOptionLegacy( 'removeComments', $x );
447  }
448 
453  public function getEnableLimitReport() {
454  return $this->getOption( 'enableLimitReport' );
455  }
456 
462  public function enableLimitReport( $x = true ) {
463  return $this->setOptionLegacy( 'enableLimitReport', $x );
464  }
465 
471  public function getCleanSignatures() {
472  return $this->getOption( 'cleanSignatures' );
473  }
474 
481  public function setCleanSignatures( $x ) {
482  return $this->setOptionLegacy( 'cleanSignatures', $x );
483  }
484 
489  public function getExternalLinkTarget() {
490  return $this->getOption( 'externalLinkTarget' );
491  }
492 
498  public function setExternalLinkTarget( $x ) {
499  return $this->setOptionLegacy( 'externalLinkTarget', $x );
500  }
501 
506  public function getDisableContentConversion() {
507  return $this->getOption( 'disableContentConversion' );
508  }
509 
515  public function disableContentConversion( $x = true ) {
516  return $this->setOptionLegacy( 'disableContentConversion', $x );
517  }
518 
523  public function getDisableTitleConversion() {
524  return $this->getOption( 'disableTitleConversion' );
525  }
526 
532  public function disableTitleConversion( $x = true ) {
533  return $this->setOptionLegacy( 'disableTitleConversion', $x );
534  }
535 
540  public function getThumbSize() {
541  return $this->getOption( 'thumbsize' );
542  }
543 
549  public function setThumbSize( $x ) {
550  return $this->setOptionLegacy( 'thumbsize', $x );
551  }
552 
557  public function getStubThreshold() {
558  return $this->getOption( 'stubthreshold' );
559  }
560 
566  public function setStubThreshold( $x ) {
567  return $this->setOptionLegacy( 'stubthreshold', $x );
568  }
569 
574  public function getIsPreview() {
575  return $this->getOption( 'isPreview' );
576  }
577 
583  public function setIsPreview( $x ) {
584  return $this->setOptionLegacy( 'isPreview', $x );
585  }
586 
591  public function getIsSectionPreview() {
592  return $this->getOption( 'isSectionPreview' );
593  }
594 
600  public function setIsSectionPreview( $x ) {
601  return $this->setOptionLegacy( 'isSectionPreview', $x );
602  }
603 
608  public function getIsPrintable() {
609  return $this->getOption( 'printable' );
610  }
611 
617  public function setIsPrintable( $x ) {
618  return $this->setOptionLegacy( 'printable', $x );
619  }
620 
625  public function getPreSaveTransform() {
626  return $this->getOption( 'preSaveTransform' );
627  }
628 
634  public function setPreSaveTransform( $x ) {
635  return $this->setOptionLegacy( 'preSaveTransform', $x );
636  }
637 
642  public function getDateFormat() {
643  return $this->getOption( 'dateformat' );
644  }
645 
651  private static function initDateFormat( ParserOptions $popt ) {
652  return $popt->mUser->getDatePreference();
653  }
654 
660  public function setDateFormat( $x ) {
661  return $this->setOptionLegacy( 'dateformat', $x );
662  }
663 
681  public function getUserLangObj() {
682  return $this->getOption( 'userlang' );
683  }
684 
697  public function getUserLang() {
698  return $this->getUserLangObj()->getCode();
699  }
700 
706  public function setUserLang( $x ) {
707  if ( is_string( $x ) ) {
708  $x = MediaWikiServices::getInstance()->getLanguageFactory()->getLanguage( $x );
709  }
710 
711  return $this->setOptionLegacy( 'userlang', $x );
712  }
713 
719  public function getMagicISBNLinks() {
720  return $this->getOption( 'magicISBNLinks' );
721  }
722 
728  public function getMagicPMIDLinks() {
729  return $this->getOption( 'magicPMIDLinks' );
730  }
731 
737  public function getMagicRFCLinks() {
738  return $this->getOption( 'magicRFCLinks' );
739  }
740 
755  public function getAllowUnsafeRawHtml() {
756  return $this->getOption( 'allowUnsafeRawHtml' );
757  }
758 
767  public function setAllowUnsafeRawHtml( $x ) {
768  return $this->setOptionLegacy( 'allowUnsafeRawHtml', $x );
769  }
770 
776  public function getWrapOutputClass() {
777  return $this->getOption( 'wrapclass' );
778  }
779 
787  public function setWrapOutputClass( $className ) {
788  if ( $className === true ) { // DWIM, they probably want the default class name
789  $className = 'mw-parser-output';
790  }
791  if ( $className === false ) {
792  wfDeprecated( __METHOD__ . '( false )', '1.31' );
793  }
794  return $this->setOption( 'wrapclass', $className );
795  }
796 
803  public function getCurrentRevisionCallback() {
804  wfDeprecated( __METHOD__, '1.35' );
805  $revCb = $this->getOption( 'currentRevisionCallback' );
806 
807  // As a temporary measure, while both currentRevisionCallback and
808  // currentRevisionRecordCallback are supported, retrieving one that is
809  // not set first checks if the other is set, so that the end result works
810  // regardless of which setter was used, since one extension may set a
811  // RevisionCallback and another may ask for the RevisionRecordCallback
812  if ( $revCb === [ Parser::class, 'statelessFetchRevision' ] ) {
813  // currentRevisionCallback is set to the default, check if
814  // currentRevisionRecordCallback is set (and not the default)
815  $revRecordCb = $this->getOption( 'currentRevisionRecordCallback' );
816  if ( $revRecordCb !== [ Parser::class, 'statelessFetchRevisionRecord' ] ) {
817  // currentRevisionRecordCallback is set and not the default,
818  // convert it
819  $revCb = function ( Title $title, $parser = false ) use ( $revRecordCb ) {
820  $revRecord = call_user_func(
821  $revRecordCb,
822  $title,
823  $parser ?: null
824  );
825  if ( $revRecord ) {
826  return new Revision( $revRecord );
827  }
828  return false;
829  };
830  }
831  }
832  return $revCb;
833  }
834 
842  $revRecordCb = $this->getOption( 'currentRevisionRecordCallback' );
843 
844  // See explanation above
845  if ( $revRecordCb === [ Parser::class, 'statelessFetchRevisionRecord' ] ) {
846  // currentRevisionRecordCallback is set to the default, check if
847  // currentRevisionCallback is set (and not the default)
848  $revCb = $this->getOption( 'currentRevisionCallback' );
849  if ( $revCb !== [ Parser::class, 'statelessFetchRevision' ] ) {
850  // currentRevisionCallback is set and not the default, convert it
851  $revRecordCb = function ( Title $title, $parser = null ) use ( $revCb ) {
852  $rev = call_user_func( $revCb, $title, $parser ?? false );
853  if ( $rev ) {
854  return $rev->getRevisionRecord();
855  }
856  return false;
857  };
858  }
859  }
860  return $revRecordCb;
861  }
862 
870  public function setCurrentRevisionCallback( $x ) {
871  wfDeprecated( __METHOD__, '1.35' );
872  return $this->setOptionLegacy( 'currentRevisionCallback', $x );
873  }
874 
882  public function setCurrentRevisionRecordCallback( $x ) {
883  return $this->setOption( 'currentRevisionRecordCallback', $x );
884  }
885 
890  public function getTemplateCallback() {
891  return $this->getOption( 'templateCallback' );
892  }
893 
899  public function setTemplateCallback( $x ) {
900  return $this->setOptionLegacy( 'templateCallback', $x );
901  }
902 
913  public function getSpeculativeRevId() {
914  return $this->getOption( 'speculativeRevId' );
915  }
916 
927  public function getSpeculativePageId() {
928  return $this->getOption( 'speculativePageId' );
929  }
930 
937  private static function initSpeculativeRevId( ParserOptions $popt ) {
938  $cb = $popt->getOption( 'speculativeRevIdCallback' );
939  $id = $cb ? $cb() : null;
940 
941  // returning null would result in this being re-called every access
942  return $id ?? false;
943  }
944 
951  private static function initSpeculativePageId( ParserOptions $popt ) {
952  $cb = $popt->getOption( 'speculativePageIdCallback' );
953  $id = $cb ? $cb() : null;
954 
955  // returning null would result in this being re-called every access
956  return $id ?? false;
957  }
958 
965  public function setSpeculativeRevIdCallback( $x ) {
966  $this->setOption( 'speculativeRevId', null ); // reset
967  return $this->setOption( 'speculativeRevIdCallback', $x );
968  }
969 
976  public function setSpeculativePageIdCallback( $x ) {
977  $this->setOption( 'speculativePageId', null ); // reset
978  return $this->setOption( 'speculativePageIdCallback', $x );
979  }
980 
985  public function getTimestamp() {
986  if ( !isset( $this->mTimestamp ) ) {
987  $this->mTimestamp = wfTimestampNow();
988  }
989  return $this->mTimestamp;
990  }
991 
997  public function setTimestamp( $x ) {
998  return wfSetVar( $this->mTimestamp, $x );
999  }
1000 
1009  public function setRedirectTarget( $title ) {
1010  $this->redirectTarget = $title;
1011  }
1012 
1019  public function getRedirectTarget() {
1020  return $this->redirectTarget;
1021  }
1022 
1029  public function addExtraKey( $key ) {
1030  $this->mExtraKey .= '!' . $key;
1031  }
1032 
1037  public function getUser() {
1038  return $this->mUser;
1039  }
1040 
1047  public function __construct( $user = null, $lang = null ) {
1048  if ( $user === null ) {
1049  wfDeprecated( __CLASS__ . ' being created with a User object', '1.36' );
1050  global $wgUser;
1051  if ( $wgUser === null ) {
1052  $user = new User;
1053  } else {
1054  $user = $wgUser;
1055  }
1056  }
1057  if ( $lang === null ) {
1058  global $wgLang;
1060  $lang = $wgLang;
1061  }
1062  $this->initialiseFromUser( $user, $lang );
1063  }
1064 
1072  public static function newFromAnon() {
1073  return new ParserOptions( new User,
1074  MediaWikiServices::getInstance()->getContentLanguage() );
1075  }
1076 
1086  public static function newFromUser( $user ) {
1087  return new ParserOptions( $user );
1088  }
1089 
1099  public static function newFromUserAndLang( User $user, Language $lang ) {
1100  return new ParserOptions( $user, $lang );
1101  }
1102 
1111  public static function newFromContext( IContextSource $context ) {
1112  return new ParserOptions( $context->getUser(), $context->getLanguage() );
1113  }
1114 
1133  public static function newCanonical( $context = null, $userLang = null ) {
1134  if ( $context instanceof IContextSource ) {
1135  $ret = self::newFromContext( $context );
1136  } elseif ( $context === 'canonical' ) {
1137  $ret = self::newFromAnon();
1138  } elseif ( $context instanceof User || $context === null ) {
1139  if ( $context === null ) {
1140  wfDeprecated( __METHOD__ . ' with no user', '1.35' );
1141 
1142  // Avoid sending out another deprecation notice from calling
1143  // __construct with null
1144  // TODO remove support for this instead
1145  global $wgUser;
1146  $context = $wgUser;
1147  }
1148  $ret = new self( $context, $userLang );
1149  } else {
1150  throw new InvalidArgumentException(
1151  '$context must be an IContextSource, the string "canonical", a User, or null'
1152  );
1153  }
1154 
1155  foreach ( self::getCanonicalOverrides() as $k => $v ) {
1156  $ret->setOption( $k, $v );
1157  }
1158  return $ret;
1159  }
1160 
1170  private static function getDefaults() {
1176  $languageConverterFactory = MediaWikiServices::getInstance()->getLanguageConverterFactory();
1177 
1178  if ( self::$defaults === null ) {
1179  // *UPDATE* ParserOptions::matches() if any of this changes as needed
1180  self::$defaults = [
1181  'dateformat' => null,
1182  'interfaceMessage' => false,
1183  'targetLanguage' => null,
1184  'removeComments' => true,
1185  'enableLimitReport' => false,
1186  'preSaveTransform' => true,
1187  'isPreview' => false,
1188  'isSectionPreview' => false,
1189  'printable' => false,
1190  'allowUnsafeRawHtml' => true,
1191  'wrapclass' => 'mw-parser-output',
1192  'currentRevisionCallback' => [ Parser::class, 'statelessFetchRevision' ],
1193  'currentRevisionRecordCallback' => [ Parser::class, 'statelessFetchRevisionRecord' ],
1194  'templateCallback' => [ Parser::class, 'statelessFetchTemplate' ],
1195  'speculativeRevIdCallback' => null,
1196  'speculativeRevId' => null,
1197  'speculativePageIdCallback' => null,
1198  'speculativePageId' => null,
1199  ];
1200 
1201  Hooks::runner()->onParserOptionsRegister(
1202  self::$defaults,
1203  self::$inCacheKey,
1204  self::$lazyOptions
1205  );
1206 
1207  ksort( self::$inCacheKey );
1208  }
1209 
1210  // Unit tests depend on being able to modify the globals at will
1211  return self::$defaults + [
1212  'interwikiMagic' => $wgInterwikiMagic,
1213  'allowExternalImages' => $wgAllowExternalImages,
1214  'allowExternalImagesFrom' => $wgAllowExternalImagesFrom,
1215  'enableImageWhitelist' => $wgEnableImageWhitelist,
1216  'allowSpecialInclusion' => $wgAllowSpecialInclusion,
1217  'maxIncludeSize' => $wgMaxArticleSize * 1024,
1218  'maxPPNodeCount' => $wgMaxPPNodeCount,
1219  'maxPPExpandDepth' => $wgMaxPPExpandDepth,
1220  'maxTemplateDepth' => $wgMaxTemplateDepth,
1221  'expensiveParserFunctionLimit' => $wgExpensiveParserFunctionLimit,
1222  'externalLinkTarget' => $wgExternalLinkTarget,
1223  'cleanSignatures' => $wgCleanSignatures,
1224  'disableContentConversion' => $languageConverterFactory->isConversionDisabled(),
1225  'disableTitleConversion' => $languageConverterFactory->isLinkConversionDisabled(),
1226  'magicISBNLinks' => $wgEnableMagicLinks['ISBN'],
1227  'magicPMIDLinks' => $wgEnableMagicLinks['PMID'],
1228  'magicRFCLinks' => $wgEnableMagicLinks['RFC'],
1229  'numberheadings' => User::getDefaultOption( 'numberheadings' ),
1230  'thumbsize' => User::getDefaultOption( 'thumbsize' ),
1231  'stubthreshold' => 0,
1232  'userlang' => MediaWikiServices::getInstance()->getContentLanguage(),
1233  ];
1234  }
1235 
1245  private static function getCanonicalOverrides() {
1247 
1248  return [
1249  'enableLimitReport' => $wgEnableParserLimitReporting,
1250  ];
1251  }
1252 
1259  private function initialiseFromUser( $user, $lang ) {
1260  $this->options = self::getDefaults();
1261 
1262  $this->mUser = $user;
1263  $this->options['numberheadings'] = $user->getOption( 'numberheadings' );
1264  $this->options['thumbsize'] = $user->getOption( 'thumbsize' );
1265  $this->options['stubthreshold'] = $user->getStubThreshold();
1266  $this->options['userlang'] = $lang;
1267  }
1268 
1278  public function matches( ParserOptions $other ) {
1279  // Compare most options
1280  $options = array_keys( $this->options );
1281  $options = array_diff( $options, [
1282  'enableLimitReport', // only affects HTML comments
1283  'tidy', // Has no effect since 1.35; removed in 1.36
1284  ] );
1285  foreach ( $options as $option ) {
1286  // Resolve any lazy options
1287  $this->lazyLoadOption( $option );
1288  $other->lazyLoadOption( $option );
1289 
1290  $o1 = $this->optionToString( $this->options[$option] );
1291  $o2 = $this->optionToString( $other->options[$option] );
1292  if ( $o1 !== $o2 ) {
1293  return false;
1294  }
1295  }
1296 
1297  // Compare most other fields
1298  $fields = array_keys( get_class_vars( __CLASS__ ) );
1299  $fields = array_diff( $fields, [
1300  'defaults', // static
1301  'lazyOptions', // static
1302  'inCacheKey', // static
1303  'callbacks', // static
1304  'options', // Already checked above
1305  'onAccessCallback', // only used for ParserOutput option tracking
1306  ] );
1307  foreach ( $fields as $field ) {
1308  if ( !is_object( $this->$field ) && $this->$field !== $other->$field ) {
1309  return false;
1310  }
1311  }
1312 
1313  return true;
1314  }
1315 
1321  public function matchesForCacheKey( ParserOptions $other ) {
1322  foreach ( self::allCacheVaryingOptions() as $option ) {
1323  // Populate any lazy options
1324  $this->lazyLoadOption( $option );
1325  $other->lazyLoadOption( $option );
1326 
1327  $o1 = $this->optionToString( $this->options[$option] );
1328  $o2 = $this->optionToString( $other->options[$option] );
1329  if ( $o1 !== $o2 ) {
1330  return false;
1331  }
1332  }
1333 
1334  return true;
1335  }
1336 
1342  public function registerWatcher( $callback ) {
1343  $this->onAccessCallback = $callback;
1344  }
1345 
1354  public function optionUsed( $optionName ) {
1355  if ( $this->onAccessCallback ) {
1356  call_user_func( $this->onAccessCallback, $optionName );
1357  }
1358  }
1359 
1365  public static function allCacheVaryingOptions() {
1366  // Trigger a call to the 'ParserOptionsRegister' hook if it hasn't
1367  // already been called.
1368  if ( self::$defaults === null ) {
1370  }
1371  return array_keys( array_filter( self::$inCacheKey ) );
1372  }
1373 
1379  private function optionToString( $value ) {
1380  if ( $value === true ) {
1381  return '1';
1382  } elseif ( $value === false ) {
1383  return '0';
1384  } elseif ( $value === null ) {
1385  return '';
1386  } elseif ( $value instanceof Language ) {
1387  return $value->getCode();
1388  } elseif ( is_array( $value ) ) {
1389  return '[' . implode( ',', array_map( [ $this, 'optionToString' ], $value ) ) . ']';
1390  } else {
1391  return (string)$value;
1392  }
1393  }
1394 
1407  public function optionsHash( $forOptions, $title = null ) {
1408  global $wgRenderHashAppend;
1409 
1411 
1412  // Resolve any lazy options
1413  $lazyOpts = array_intersect( $forOptions, $inCacheKey, array_keys( self::$lazyOptions ) );
1414  foreach ( $lazyOpts as $k ) {
1415  $this->lazyLoadOption( $k );
1416  }
1417 
1420 
1421  // We only include used options with non-canonical values in the key
1422  // so adding a new option doesn't invalidate the entire parser cache.
1423  // The drawback to this is that changing the default value of an option
1424  // requires manual invalidation of existing cache entries, as mentioned
1425  // in the docs on the relevant methods and hooks.
1426  $values = [];
1427  foreach ( array_intersect( $inCacheKey, $forOptions ) as $option ) {
1428  $v = $this->optionToString( $options[$option] );
1429  $d = $this->optionToString( $defaults[$option] );
1430  if ( $v !== $d ) {
1431  $values[] = "$option=$v";
1432  }
1433  }
1434 
1435  $confstr = $values ? implode( '!', $values ) : 'canonical';
1436 
1437  // add in language specific options, if any
1438  // @todo FIXME: This is just a way of retrieving the url/user preferred variant
1439 
1440  $lang = $title ? $title->getPageLanguage() :
1441  MediaWikiServices::getInstance()->getContentLanguage();
1442  $converter = MediaWikiServices::getInstance()->getLanguageConverterFactory()
1443  ->getLanguageConverter( $lang );
1444  $confstr .= $converter->getExtraHashOptions();
1445 
1446  $confstr .= $wgRenderHashAppend;
1447 
1448  if ( $this->mExtraKey != '' ) {
1449  $confstr .= $this->mExtraKey;
1450  }
1451 
1452  // Give a chance for extensions to modify the hash, if they have
1453  // extra options or other effects on the parser cache.
1454  Hooks::runner()->onPageRenderingHash( $confstr, $this->getUser(), $forOptions );
1455 
1456  // Make it a valid memcached key fragment
1457  $confstr = str_replace( ' ', '_', $confstr );
1458 
1459  return $confstr;
1460  }
1461 
1467  public function isSafeToCache() {
1469  foreach ( $this->options as $option => $value ) {
1470  if ( empty( self::$inCacheKey[$option] ) && empty( self::$callbacks[$option] ) ) {
1471  $v = $this->optionToString( $value );
1472  $d = $this->optionToString( $defaults[$option] );
1473  if ( $v !== $d ) {
1474  return false;
1475  }
1476  }
1477  }
1478  return true;
1479  }
1480 
1491  public function setupFakeRevision( $title, $content, $user ) {
1492  $oldCallback = $this->setCurrentRevisionRecordCallback(
1493  function (
1494  $titleToCheck, $parser = null ) use ( $title, $content, $user, &$oldCallback
1495  ) {
1496  if ( $titleToCheck->equals( $title ) ) {
1497  $revRecord = new MutableRevisionRecord( $title );
1498  $revRecord->setContent( SlotRecord::MAIN, $content )
1499  ->setUser( $user )
1500  ->setTimestamp( MWTimestamp::now( TS_MW ) )
1501  ->setPageId( $title->getArticleID() )
1502  ->setParentId( $title->getLatestRevID() );
1503  return $revRecord;
1504  } else {
1505  return call_user_func( $oldCallback, $titleToCheck, $parser );
1506  }
1507  }
1508  );
1509 
1510  global $wgHooks;
1511  $wgHooks['TitleExists'][] =
1512  function ( $titleToCheck, &$exists ) use ( $title ) {
1513  if ( $titleToCheck->equals( $title ) ) {
1514  $exists = true;
1515  }
1516  };
1517  end( $wgHooks['TitleExists'] );
1518  $key = key( $wgHooks['TitleExists'] );
1519  $linkCache = MediaWikiServices::getInstance()->getLinkCache();
1520  $linkCache->clearBadLink( $title->getPrefixedDBkey() );
1521  return new ScopedCallback( function () use ( $title, $key, $linkCache ) {
1522  global $wgHooks;
1523  unset( $wgHooks['TitleExists'][$key] );
1524  $linkCache->clearLink( $title );
1525  } );
1526  }
1527 }
1528 
User\getDefaultOption
static getDefaultOption( $opt)
Get a given default option value.
Definition: User.php:1551
ParserOptions\setMaxIncludeSize
setMaxIncludeSize( $x)
Maximum size of template expansions, in bytes.
Definition: ParserOptions.php:365
ParserOptions\getMagicPMIDLinks
getMagicPMIDLinks()
Are magic PMID links enabled?
Definition: ParserOptions.php:728
ParserOptions
Set options of the Parser.
Definition: ParserOptions.php:44
ParserOptions\setOptionLegacy
setOptionLegacy( $name, $value)
Legacy implementation.
Definition: ParserOptions.php:178
ParserOptions\getAllowExternalImagesFrom
getAllowExternalImagesFrom()
External images to allow.
Definition: ParserOptions.php:233
ParserOptions\getWrapOutputClass
getWrapOutputClass()
Class to use to wrap output from Parser::parse()
Definition: ParserOptions.php:776
ParserOptions\getExpensiveParserFunctionLimit
getExpensiveParserFunctionLimit()
Maximum number of calls per parse to expensive parser functions.
Definition: ParserOptions.php:416
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:591
$wgMaxArticleSize
$wgMaxArticleSize
Maximum article size in kilobytes.
Definition: DefaultSettings.php:2398
ParserOptions\getRemoveComments
getRemoveComments()
Remove HTML comments.
Definition: ParserOptions.php:435
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:767
ParserOptions\disableContentConversion
disableContentConversion( $x=true)
Whether content conversion should be disabled.
Definition: ParserOptions.php:515
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:166
$lang
if(!isset( $args[0])) $lang
Definition: testCompression.php:37
ParserOptions\initialiseFromUser
initialiseFromUser( $user, $lang)
Get user options.
Definition: ParserOptions.php:1259
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:1560
$wgMaxTemplateDepth
$wgMaxTemplateDepth
Maximum recursion depth for templates within templates.
Definition: DefaultSettings.php:4572
ParserOptions\getIsPreview
getIsPreview()
Parsing the page for a "preview" operation?
Definition: ParserOptions.php:574
ParserOptions\getDisableTitleConversion
getDisableTitleConversion()
Whether title conversion should be disabled.
Definition: ParserOptions.php:523
ParserOptions\setAllowExternalImages
setAllowExternalImages( $x)
Allow all external images inline?
Definition: ParserOptions.php:221
ParserOptions\setTemplateCallback
setTemplateCallback( $x)
Callback for template fetching; first argument to call_user_func().
Definition: ParserOptions.php:899
ParserOptions\setIsPreview
setIsPreview( $x)
Parsing the page for a "preview" operation?
Definition: ParserOptions.php:583
ParserOptions\setTargetLanguage
setTargetLanguage( $x)
Target language for the parse.
Definition: ParserOptions.php:348
ParserOptions\getInterfaceMessage
getInterfaceMessage()
Parsing an interface message?
Definition: ParserOptions.php:322
ParserOptions\setIsSectionPreview
setIsSectionPreview( $x)
Parsing the page for a "preview" operation on a single section?
Definition: ParserOptions.php:600
ParserOptions\getSpeculativeRevId
getSpeculativeRevId()
A guess for {{REVISIONID}}, calculated using the callback provided via setSpeculativeRevIdCallback().
Definition: ParserOptions.php:913
ParserOptions\newFromAnon
static newFromAnon()
Get a ParserOptions object for an anonymous user.
Definition: ParserOptions.php:1072
ParserOptions\setEnableImageWhitelist
setEnableImageWhitelist( $x)
Use the on-wiki external image whitelist?
Definition: ParserOptions.php:267
ParserOptions\setWrapOutputClass
setWrapOutputClass( $className)
CSS class to use to wrap output from Parser::parse()
Definition: ParserOptions.php:787
ParserOptions\setSpeculativeRevIdCallback
setSpeculativeRevIdCallback( $x)
Callback to generate a guess for {{REVISIONID}}.
Definition: ParserOptions.php:965
ParserOptions\disableTitleConversion
disableTitleConversion( $x=true)
Whether title conversion should be disabled.
Definition: ParserOptions.php:532
ParserOptions\initDateFormat
static initDateFormat(ParserOptions $popt)
Lazy initializer for dateFormat.
Definition: ParserOptions.php:651
ParserOptions\getIsPrintable
getIsPrintable()
Parsing the printable version of the page?
Definition: ParserOptions.php:608
ParserOptions\setCurrentRevisionCallback
setCurrentRevisionCallback( $x)
Callback for current revision fetching; first argument to call_user_func().
Definition: ParserOptions.php:870
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:407
$wgLang
$wgLang
Definition: Setup.php:777
ParserOptions\getMagicRFCLinks
getMagicRFCLinks()
Are magic RFC links enabled?
Definition: ParserOptions.php:737
ParserOptions\getUserLangObj
getUserLangObj()
Get the user language used by the parser for this page and split the parser cache.
Definition: ParserOptions.php:681
ParserOptions\registerWatcher
registerWatcher( $callback)
Registers a callback for tracking which ParserOptions which are used.
Definition: ParserOptions.php:1342
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:1491
ParserOptions\getDateFormat
getDateFormat()
Date format index.
Definition: ParserOptions.php:642
Revision
Definition: Revision.php:40
ParserOptions\setOption
setOption( $name, $value)
Set an option, generically.
Definition: ParserOptions.php:161
ParserOptions\initSpeculativeRevId
static initSpeculativeRevId(ParserOptions $popt)
Callback registered with ParserOptions::$lazyOptions, triggered by getSpeculativeRevId().
Definition: ParserOptions.php:937
ParserOptions\setNumberHeadings
setNumberHeadings( $x)
Automatically number headings?
Definition: ParserOptions.php:285
$wgHooks
$wgHooks
Global list of hooks.
Definition: DefaultSettings.php:7938
ParserOptions\getCanonicalOverrides
static getCanonicalOverrides()
Get "canonical" non-default option values.
Definition: ParserOptions.php:1245
wfDeprecated
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that $function is deprecated.
Definition: GlobalFunctions.php:1033
ParserOptions\getRedirectTarget
getRedirectTarget()
Get the previously-set redirect target.
Definition: ParserOptions.php:1019
ParserOptions\newFromUserAndLang
static newFromUserAndLang(User $user, Language $lang)
Get a ParserOptions object from a given user and language.
Definition: ParserOptions.php:1099
ParserOptions\setUserLang
setUserLang( $x)
Set the user language used by the parser for this page and split the parser cache.
Definition: ParserOptions.php:706
ParserOptions\getAllowSpecialInclusion
getAllowSpecialInclusion()
Allow inclusion of special pages?
Definition: ParserOptions.php:293
$wgAllowExternalImagesFrom
$wgAllowExternalImagesFrom
If the above is false, you can specify an exception here.
Definition: DefaultSettings.php:4618
ParserOptions\getMaxIncludeSize
getMaxIncludeSize()
Maximum size of template expansions, in bytes.
Definition: ParserOptions.php:356
ParserOptions\$mTimestamp
string null $mTimestamp
Timestamp used for {{CURRENTDAY}} etc.
Definition: ParserOptions.php:99
$wgExpensiveParserFunctionLimit
$wgExpensiveParserFunctionLimit
Maximum number of calls per parse to expensive parser functions such as PAGESINCATEGORY.
Definition: DefaultSettings.php:4734
ParserOptions\setThumbSize
setThumbSize( $x)
Thumb size preferred by the user.
Definition: ParserOptions.php:549
ParserOptions\getEnableImageWhitelist
getEnableImageWhitelist()
Use the on-wiki external image whitelist?
Definition: ParserOptions.php:256
$wgInterwikiMagic
$wgInterwikiMagic
Treat language links as magic connectors, not inline links.
Definition: DefaultSettings.php:3127
ParserOptions\setExternalLinkTarget
setExternalLinkTarget( $x)
Target attribute for external links.
Definition: ParserOptions.php:498
ParserOptions\setDateFormat
setDateFormat( $x)
Date format index.
Definition: ParserOptions.php:660
ParserOptions\getTargetLanguage
getTargetLanguage()
Target language for the parse.
Definition: ParserOptions.php:339
$title
$title
Definition: testCompression.php:38
ParserOptions\initSpeculativePageId
static initSpeculativePageId(ParserOptions $popt)
Callback registered with ParserOptions::$lazyOptions, triggered by getSpeculativePageId().
Definition: ParserOptions.php:951
ParserOptions\setAllowSpecialInclusion
setAllowSpecialInclusion( $x)
Allow inclusion of special pages?
Definition: ParserOptions.php:302
$wgMaxPPExpandDepth
$wgMaxPPExpandDepth
Definition: DefaultSettings.php:4577
ParserOptions\getDefaults
static getDefaults()
Get default option values.
Definition: ParserOptions.php:1170
ParserOptions\getExternalLinkTarget
getExternalLinkTarget()
Target attribute for external links.
Definition: ParserOptions.php:489
ParserOptions\$onAccessCallback
callable null $onAccessCallback
Function to be called when an option is accessed.
Definition: ParserOptions.php:113
$wgEnableMagicLinks
$wgEnableMagicLinks
Enable the magic links feature of automatically turning ISBN xxx, PMID xxx, RFC xxx into links.
Definition: DefaultSettings.php:4759
wfTimestampNow
wfTimestampNow()
Convenience function; returns MediaWiki timestamp for the present time.
Definition: GlobalFunctions.php:1860
ParserOptions\getStubThreshold
getStubThreshold()
Thumb size preferred by the user.
Definition: ParserOptions.php:557
$wgExternalLinkTarget
$wgExternalLinkTarget
Set a default target for external links, e.g.
Definition: DefaultSettings.php:4687
ParserOptions\$options
array $options
Current values for all options that are relevant for caching.
Definition: ParserOptions.php:92
ParserOptions\getUserLang
getUserLang()
Same as getUserLangObj() but returns a string instead.
Definition: ParserOptions.php:697
ParserOptions\getPreSaveTransform
getPreSaveTransform()
Transform wiki markup when saving the page?
Definition: ParserOptions.php:625
ParserOptions\setStubThreshold
setStubThreshold( $x)
Thumb size preferred by the user.
Definition: ParserOptions.php:566
ParserOptions\getOption
getOption( $name)
Fetch an option and track that is was accessed.
Definition: ParserOptions.php:134
ParserOptions\$mExtraKey
$mExtraKey
Appended to the options hash.
Definition: ParserOptions.php:126
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:755
ParserOptions\getDisableContentConversion
getDisableContentConversion()
Whether content conversion should be disabled.
Definition: ParserOptions.php:506
ParserOptions\optionToString
optionToString( $value)
Convert an option to a string value.
Definition: ParserOptions.php:1379
ParserOptions\matchesForCacheKey
matchesForCacheKey(ParserOptions $other)
Definition: ParserOptions.php:1321
ParserOptions\optionUsed
optionUsed( $optionName)
Called when an option is accessed.
Definition: ParserOptions.php:1354
$content
$content
Definition: router.php:76
ParserOptions\getSpeculativePageId
getSpeculativePageId()
A guess for {{PAGEID}}, calculated using the callback provided via setSpeculativeRevPageCallback().
Definition: ParserOptions.php:927
ParserOptions\setTimestamp
setTimestamp( $x)
Timestamp used for {{CURRENTDAY}} etc.
Definition: ParserOptions.php:997
ParserOptions\setSpeculativePageIdCallback
setSpeculativePageIdCallback( $x)
Callback to generate a guess for {{PAGEID}}.
Definition: ParserOptions.php:976
ParserOptions\setCleanSignatures
setCleanSignatures( $x)
Clean up signature texts?
Definition: ParserOptions.php:481
ParserOptions\newFromContext
static newFromContext(IContextSource $context)
Get a ParserOptions object from a IContextSource object.
Definition: ParserOptions.php:1111
Revision\MutableRevisionRecord
Definition: MutableRevisionRecord.php:45
ParserOptions\getCurrentRevisionCallback
getCurrentRevisionCallback()
Callback for current revision fetching; first argument to call_user_func().
Definition: ParserOptions.php:803
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:7793
ParserOptions\getTemplateCallback
getTemplateCallback()
Callback for template fetching; first argument to call_user_func().
Definition: ParserOptions.php:890
ParserOptions\newCanonical
static newCanonical( $context=null, $userLang=null)
Creates a "canonical" ParserOptions object.
Definition: ParserOptions.php:1133
ParserOptions\setRemoveComments
setRemoveComments( $x)
Remove HTML comments.
Definition: ParserOptions.php:445
ParserOptions\setInterwikiMagic
setInterwikiMagic( $x)
Specify whether to extract interlanguage links.
Definition: ParserOptions.php:202
IContextSource\getUser
getUser()
ParserOptions\lazyLoadOption
lazyLoadOption( $name)
Definition: ParserOptions.php:147
ParserOptions\setRedirectTarget
setRedirectTarget( $title)
Note that setting or changing this does not make the page a redirect or change its target,...
Definition: ParserOptions.php:1009
ParserOptions\setExpensiveParserFunctionLimit
setExpensiveParserFunctionLimit( $x)
Maximum number of calls per parse to expensive parser functions.
Definition: ParserOptions.php:426
ParserOptions\getTimestamp
getTimestamp()
Timestamp used for {{CURRENTDAY}} etc.
Definition: ParserOptions.php:985
ParserOptions\setMaxPPNodeCount
setMaxPPNodeCount( $x)
Maximum number of nodes touched by PPFrame::expand()
Definition: ParserOptions.php:382
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:471
ParserOptions\$redirectTarget
Title null $redirectTarget
If the page being parsed is a redirect, this should hold the redirect target.
Definition: ParserOptions.php:121
ParserOptions\setAllowExternalImagesFrom
setAllowExternalImagesFrom( $x)
External images to allow.
Definition: ParserOptions.php:247
ParserOptions\matches
matches(ParserOptions $other)
Check if these options match that of another options set.
Definition: ParserOptions.php:1278
ParserOptions\enableLimitReport
enableLimitReport( $x=true)
Enable limit report in an HTML comment on output.
Definition: ParserOptions.php:462
Title
Represents a title within MediaWiki.
Definition: Title.php:46
ParserOptions\__construct
__construct( $user=null, $lang=null)
Definition: ParserOptions.php:1047
ParserOptions\getInterwikiMagic
getInterwikiMagic()
Whether to extract interlanguage links.
Definition: ParserOptions.php:193
ParserOptions\$lazyOptions
static callable[] $lazyOptions
Lazy-loaded options.
Definition: ParserOptions.php:57
ParserOptions\$mUser
User $mUser
Stored user object.
Definition: ParserOptions.php:106
ParserOptions\setInterfaceMessage
setInterfaceMessage( $x)
Parsing an interface message?
Definition: ParserOptions.php:331
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:1365
$wgCleanSignatures
$wgCleanSignatures
If true, removes (by substituting) templates in signatures.
Definition: DefaultSettings.php:4599
ParserOptions\getUser
getUser()
Current user.
Definition: ParserOptions.php:1037
ParserOptions\getThumbSize
getThumbSize()
Thumb size preferred by the user.
Definition: ParserOptions.php:540
ParserOptions\getMagicISBNLinks
getMagicISBNLinks()
Are magic ISBN links enabled?
Definition: ParserOptions.php:719
ParserOptions\setIsPrintable
setIsPrintable( $x)
Parsing the printable version of the page?
Definition: ParserOptions.php:617
ParserOptions\getMaxPPNodeCount
getMaxPPNodeCount()
Maximum number of nodes touched by PPFrame::expand()
Definition: ParserOptions.php:373
$wgRenderHashAppend
$wgRenderHashAppend
Append a configured value to the parser cache and the sitenotice key so that they can be kept separat...
Definition: DefaultSettings.php:2809
ParserOptions\getCurrentRevisionRecordCallback
getCurrentRevisionRecordCallback()
Callback for current revision fetching; first argument to call_user_func().
Definition: ParserOptions.php:841
ParserOptions\getMaxPPExpandDepth
getMaxPPExpandDepth()
Maximum recursion depth in PPFrame::expand()
Definition: ParserOptions.php:390
ParserOptions\getEnableLimitReport
getEnableLimitReport()
Enable limit report in an HTML comment on output.
Definition: ParserOptions.php:453
ParserOptions\getNumberHeadings
getNumberHeadings()
Automatically number headings?
Definition: ParserOptions.php:276
ParserOptions\isSafeToCache
isSafeToCache()
Test whether these options are safe to cache.
Definition: ParserOptions.php:1467
ParserOptions\getMaxTemplateDepth
getMaxTemplateDepth()
Maximum recursion depth for templates within templates.
Definition: ParserOptions.php:398
ParserOptions\setPreSaveTransform
setPreSaveTransform( $x)
Transform wiki markup when saving the page?
Definition: ParserOptions.php:634
User
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition: User.php:56
ParserOptions\$callbacks
static array $callbacks
Specify pseudo-options that are actually callbacks.
Definition: ParserOptions.php:80
StubObject\unstub
static unstub(&$obj)
Unstubs an object, if it is a stub object.
Definition: StubObject.php:101
$wgMaxPPNodeCount
$wgMaxPPNodeCount
A complexity limit on template expansion: the maximum number of nodes visited by PPFrame::expand()
Definition: DefaultSettings.php:4564
ParserOptions\setCurrentRevisionRecordCallback
setCurrentRevisionRecordCallback( $x)
Callback for current revision fetching; first argument to call_user_func().
Definition: ParserOptions.php:882
Language
Internationalisation code See https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation for more...
Definition: Language.php:42
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:1407
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:210
ParserOptions\newFromUser
static newFromUser( $user)
Get a ParserOptions object from a given user.
Definition: ParserOptions.php:1086
$wgAllowExternalImages
$wgAllowExternalImages
Whether to allow inline image pointing to other websites.
Definition: DefaultSettings.php:4604
$wgEnableImageWhitelist
$wgEnableImageWhitelist
If $wgAllowExternalImages is false, you can allow an on-wiki allow list of regular expression fragmen...
Definition: DefaultSettings.php:4631
ParserOptions\addExtraKey
addExtraKey( $key)
Extra key that should be present in the parser cache key.
Definition: ParserOptions.php:1029
$wgAllowSpecialInclusion
$wgAllowSpecialInclusion
Allow special page inclusions such as {{Special:Allpages}}.
Definition: DefaultSettings.php:8377