MediaWiki  master
ParserOutput.php
Go to the documentation of this file.
1 <?php
2 
11 use Wikimedia\Reflection\GhostFieldAccessTrait;
12 
35 class ParserOutput extends CacheTime {
36  use GhostFieldAccessTrait;
38 
46 
50  public const SUPPORTS_UNWRAP_TRANSFORM = 1;
51 
55  private $mText = null;
56 
61  private $mLanguageLinks;
62 
66  private $mCategories;
67 
71  private $mIndicators = [];
72 
76  private $mTitleText;
77 
83  private $mLinks = [];
84 
89  private $mLinksSpecial = [];
90 
95  private $mTemplates = [];
96 
101  private $mTemplateIds = [];
102 
106  private $mImages = [];
107 
111  private $mFileSearchOptions = [];
112 
116  private $mExternalLinks = [];
117 
122  private $mInterwikiLinks = [];
123 
127  private $mNewSection = false;
128 
132  private $mHideNewSection = false;
133 
137  private $mNoGallery = false;
138 
142  private $mHeadItems = [];
143 
147  private $mModules = [];
148 
152  private $mModuleStyles = [];
153 
157  private $mJsConfigVars = [];
158 
162  private $mOutputHooks = [];
163 
168  private $mWarnings = [];
169 
173  private $mSections = [];
174 
178  private $mProperties = [];
179 
183  private $mTOCHTML = '';
184 
188  private $mTimestamp;
189 
193  private $mEnableOOUI = false;
194 
198  private $mIndexPolicy = '';
199 
203  private $mExtensionData = [];
204 
208  private $mLimitReportData = [];
209 
211  private $mLimitReportJSData = [];
212 
214  private $mCacheMessage = '';
215 
219  private $mParseStartTime = [];
220 
224  private $mPreventClickjacking = false;
225 
229  private $mExtraScriptSrcs = [];
230 
234  private $mExtraDefaultSrcs = [];
235 
239  private $mExtraStyleSrcs = [];
240 
244  private $mFlags = [];
245 
247  private const SPECULATIVE_FIELDS = [
248  'speculativePageIdUsed',
249  'mSpeculativeRevId',
250  'revisionTimestampUsed'
251  ];
252 
259 
262 
266  private $mWrapperDivClasses = [];
267 
269  private $mMaxAdaptiveExpiry = INF;
270 
271  private const EDITSECTION_REGEX =
272  '#<(?:mw:)?editsection page="(.*?)" section="(.*?)"(?:/>|>(.*?)(</(?:mw:)?editsection>))#s';
273 
274  // finalizeAdaptiveCacheExpiry() uses TTL = MAX( m * PARSE_TIME + b, MIN_AR_TTL)
275  // Current values imply that m=3933.333333 and b=-333.333333
276  // See https://www.nngroup.com/articles/website-response-times/
277  private const PARSE_FAST_SEC = 0.100; // perceived "fast" page parse
278  private const PARSE_SLOW_SEC = 1.0; // perceived "slow" page parse
279  private const FAST_AR_TTL = 60; // adaptive TTL for "fast" pages
280  private const SLOW_AR_TTL = 3600; // adaptive TTL for "slow" pages
281  private const MIN_AR_TTL = 15; // min adaptive TTL (for pool counter, and edit stashing)
282 
292  public function __construct( $text = '', $languageLinks = [], $categoryLinks = [],
293  $unused = false, $titletext = ''
294  ) {
295  $this->mText = $text;
296  $this->mLanguageLinks = $languageLinks;
297  $this->mCategories = $categoryLinks;
298  $this->mTitleText = $titletext;
299  }
300 
311  public function hasText() {
312  return ( $this->mText !== null );
313  }
314 
323  public function getRawText() {
324  if ( $this->mText === null ) {
325  throw new LogicException( 'This ParserOutput contains no text!' );
326  }
327 
328  return $this->mText;
329  }
330 
363  public function getText( $options = [] ) {
364  $options += [
365  'allowTOC' => true,
366  'injectTOC' => true,
367  'enableSectionEditLinks' => true,
368  'skin' => null,
369  'unwrap' => false,
370  'deduplicateStyles' => true,
371  'wrapperDivClass' => $this->getWrapperDivClass(),
372  'includeDebugInfo' => false,
373  ];
374  $text = $this->getRawText();
375 
376  if ( $options['includeDebugInfo'] ) {
377  $text .= $this->renderDebugInfo();
378  }
379 
380  Hooks::runner()->onParserOutputPostCacheTransform( $this, $text, $options );
381 
382  if ( $options['wrapperDivClass'] !== '' && !$options['unwrap'] ) {
383  $text = Html::rawElement( 'div', [ 'class' => $options['wrapperDivClass'] ], $text );
384  }
385 
386  if ( $options['enableSectionEditLinks'] ) {
387  // TODO: Skin should not be required.
388  // It would be better to define one or more narrow interfaces to use here,
389  // so this code doesn't have to depend on all of Skin.
390  $skin = $options['skin'] ?: RequestContext::getMain()->getSkin();
391 
392  $text = preg_replace_callback(
393  self::EDITSECTION_REGEX,
394  function ( $m ) use ( $skin ) {
395  $editsectionPage = Title::newFromText( htmlspecialchars_decode( $m[1] ) );
396  $editsectionSection = htmlspecialchars_decode( $m[2] );
397  $editsectionContent = isset( $m[4] ) ? Sanitizer::decodeCharReferences( $m[3] ) : null;
398 
399  if ( !is_object( $editsectionPage ) ) {
400  LoggerFactory::getInstance( 'Parser' )
401  ->error(
402  'ParserOutput::getText(): bad title in editsection placeholder',
403  [
404  'placeholder' => $m[0],
405  'editsectionPage' => $m[1],
406  'titletext' => $this->getTitleText(),
407  'phab' => 'T261347'
408  ]
409  );
410  return '';
411  }
412 
413  return $skin->doEditSectionLink(
414  $editsectionPage,
415  $editsectionSection,
416  $editsectionContent,
417  $skin->getLanguage()
418  );
419  },
420  $text
421  );
422  } else {
423  $text = preg_replace( self::EDITSECTION_REGEX, '', $text );
424  }
425 
426  if ( $options['allowTOC'] ) {
427  if ( $options['injectTOC'] ) {
428  $toc = $this->getTOCHTML();
429  // language conversion needs to be done on the TOC fetched
430  // from parser cache
431  // XXX doesn't check ParserOptions::getDisableContentConversion()
432  // XXX doesn't check Parser::$mDoubleUnderscores['nocontentconvert']
433  // XXX doesn't check ParserOptions::getInterfaceMessage()
434  // XXX Use DI to inject this once ::getText() is moved out
435  // of ParserOutput
436  $services = MediaWikiServices::getInstance();
437  $languageConverterFactory =
438  $services->getLanguageConverterFactory();
439  $toc = $languageConverterFactory->getLanguageConverter(
440  // XXX This was Parser::getTargetLanguage()
441  $services->getContentLanguage()
442  )->convert( $toc );
443 
444  // XXX Use DI to inject this once ::getText() is moved out
445  // of ParserOutput.
446  $tidy = MediaWikiServices::getInstance()->getTidy();
447  $toc = $tidy->tidy(
448  $toc,
449  [ Sanitizer::class, 'armorFrenchSpaces' ]
450  );
451  $text = Parser::replaceTableOfContentsMarker( $text, $toc );
452  // The line below can be removed once old content has expired
453  // from the parser cache
454  $text = str_replace( [ Parser::TOC_START, Parser::TOC_END ], '', $text );
455  } else {
456  // The line below can be removed once old content has expired
457  // from the parser cache (and Parser::TOC_PLACEHOLDER should
458  // then be made private)
459  $text = preg_replace(
460  '#' . preg_quote( Parser::TOC_START, '#' ) . '.*?' . preg_quote( Parser::TOC_END, '#' ) . '#s',
461  Parser::TOC_PLACEHOLDER,
462  $text
463  );
464  }
465  } else {
466  $text = Parser::replaceTableOfContentsMarker( $text, '' );
467  // The line below can be removed once old content has expired
468  // from the parser cache
469  $text = preg_replace(
470  '#' . preg_quote( Parser::TOC_START, '#' ) . '.*?' . preg_quote( Parser::TOC_END, '#' ) . '#s',
471  '',
472  $text
473  );
474  }
475 
476  if ( $options['deduplicateStyles'] ) {
477  $seen = [];
478  $text = preg_replace_callback(
479  '#<style\s+([^>]*data-mw-deduplicate\s*=[^>]*)>.*?</style>#s',
480  static function ( $m ) use ( &$seen ) {
481  $attr = Sanitizer::decodeTagAttributes( $m[1] );
482  if ( !isset( $attr['data-mw-deduplicate'] ) ) {
483  return $m[0];
484  }
485 
486  $key = $attr['data-mw-deduplicate'];
487  if ( !isset( $seen[$key] ) ) {
488  $seen[$key] = true;
489  return $m[0];
490  }
491 
492  // We were going to use an empty <style> here, but there
493  // was concern that would be too much overhead for browsers.
494  // So let's hope a <link> with a non-standard rel and href isn't
495  // going to be misinterpreted or mangled by any subsequent processing.
496  return Html::element( 'link', [
497  'rel' => 'mw-deduplicated-inline-style',
498  'href' => "mw-data:" . wfUrlencode( $key ),
499  ] );
500  },
501  $text
502  );
503  }
504 
505  // Expand all relative URLs
506  if ( ( $options['absoluteURLs'] ?? false ) && $text ) {
507  $text = Linker::expandLocalLinks( $text );
508  }
509 
510  // Hydrate slot section header placeholders generated by RevisionRenderer.
511  $text = preg_replace_callback(
512  '#<mw:slotheader>(.*?)</mw:slotheader>#',
513  static function ( $m ) {
514  $role = htmlspecialchars_decode( $m[1] );
515  // TODO: map to message, using the interface language. Set lang="xyz" accordingly.
516  $headerText = $role;
517  return $headerText;
518  },
519  $text
520  );
521  return $text;
522  }
523 
529  public function addCacheMessage( string $msg ) {
530  $this->mCacheMessage .= $msg;
531  }
532 
538  public function addWrapperDivClass( $class ) {
539  $this->mWrapperDivClasses[$class] = true;
540  }
541 
546  public function clearWrapperDivClass() {
547  $this->mWrapperDivClasses = [];
548  }
549 
557  public function getWrapperDivClass() {
558  return implode( ' ', array_keys( $this->mWrapperDivClasses ) );
559  }
560 
565  public function setSpeculativeRevIdUsed( $id ) {
566  $this->mSpeculativeRevId = $id;
567  }
568 
573  public function getSpeculativeRevIdUsed() {
575  }
576 
581  public function setSpeculativePageIdUsed( $id ) {
582  $this->speculativePageIdUsed = $id;
583  }
584 
589  public function getSpeculativePageIdUsed() {
591  }
592 
597  public function setRevisionTimestampUsed( $timestamp ) {
598  $this->revisionTimestampUsed = $timestamp;
599  }
600 
605  public function getRevisionTimestampUsed() {
607  }
608 
613  public function setRevisionUsedSha1Base36( $hash ) {
614  if ( $hash === null ) {
615  return; // e.g. RevisionRecord::getSha1() returned null
616  }
617 
618  if (
619  $this->revisionUsedSha1Base36 !== null &&
620  $this->revisionUsedSha1Base36 !== $hash
621  ) {
622  $this->revisionUsedSha1Base36 = ''; // mismatched
623  } else {
624  $this->revisionUsedSha1Base36 = $hash;
625  }
626  }
627 
632  public function getRevisionUsedSha1Base36() {
634  }
635 
636  public function &getLanguageLinks() {
637  return $this->mLanguageLinks;
638  }
639 
640  public function getInterwikiLinks() {
641  return $this->mInterwikiLinks;
642  }
643 
649  public function getCategoryLinks() {
650  wfDeprecated( __METHOD__, '1.38' );
651  return $this->getCategoryNames();
652  }
653 
661  public function getCategoryNames(): array {
662  return array_keys( $this->mCategories );
663  }
664 
665  public function &getCategories() {
666  return $this->mCategories;
667  }
668 
673  public function getIndicators() {
674  return $this->mIndicators;
675  }
676 
677  public function getTitleText() {
678  return $this->mTitleText;
679  }
680 
684  public function getSections() {
685  return $this->mSections;
686  }
687 
688  public function &getLinks() {
689  return $this->mLinks;
690  }
691 
696  public function &getLinksSpecial() {
697  return $this->mLinksSpecial;
698  }
699 
700  public function &getTemplates() {
701  return $this->mTemplates;
702  }
703 
704  public function &getTemplateIds() {
705  return $this->mTemplateIds;
706  }
707 
708  public function &getImages() {
709  return $this->mImages;
710  }
711 
712  public function &getFileSearchOptions() {
714  }
715 
716  public function &getExternalLinks() {
717  return $this->mExternalLinks;
718  }
719 
720  public function setNoGallery( $value ) {
721  $this->mNoGallery = (bool)$value;
722  }
723 
724  public function getNoGallery() {
725  return $this->mNoGallery;
726  }
727 
728  public function getHeadItems() {
729  return $this->mHeadItems;
730  }
731 
732  public function getModules() {
733  return $this->mModules;
734  }
735 
736  public function getModuleStyles() {
737  return $this->mModuleStyles;
738  }
739 
744  public function getJsConfigVars() {
745  return $this->mJsConfigVars;
746  }
747 
748  public function getOutputHooks() {
749  return (array)$this->mOutputHooks;
750  }
751 
752  public function getWarnings() {
753  return array_keys( $this->mWarnings );
754  }
755 
756  public function getIndexPolicy() {
757  return $this->mIndexPolicy;
758  }
759 
760  public function getTOCHTML() {
761  return $this->mTOCHTML;
762  }
763 
767  public function getTimestamp() {
768  return $this->mTimestamp;
769  }
770 
771  public function getLimitReportData() {
773  }
774 
775  public function getLimitReportJSData() {
777  }
778 
779  public function getEnableOOUI() {
780  return $this->mEnableOOUI;
781  }
782 
788  public function getExtraCSPDefaultSrcs() {
790  }
791 
797  public function getExtraCSPScriptSrcs() {
799  }
800 
806  public function getExtraCSPStyleSrcs() {
807  return $this->mExtraStyleSrcs;
808  }
809 
810  public function setText( $text ) {
811  return wfSetVar( $this->mText, $text );
812  }
813 
814  public function setLanguageLinks( $ll ) {
815  return wfSetVar( $this->mLanguageLinks, $ll );
816  }
817 
821  public function setCategoryLinks( $cl ) {
822  wfDeprecated( __METHOD__, '1.38' );
823  return wfSetVar( $this->mCategories, $cl );
824  }
825 
826  public function setTitleText( $t ) {
827  return wfSetVar( $this->mTitleText, $t );
828  }
829 
830  public function setSections( $toc ) {
831  return wfSetVar( $this->mSections, $toc );
832  }
833 
834  public function setIndexPolicy( $policy ) {
835  return wfSetVar( $this->mIndexPolicy, $policy );
836  }
837 
838  public function setTOCHTML( $tochtml ) {
839  return wfSetVar( $this->mTOCHTML, $tochtml );
840  }
841 
842  public function setTimestamp( $timestamp ) {
843  return wfSetVar( $this->mTimestamp, $timestamp );
844  }
845 
851  public function addCategory( $c, $sort ): void {
852  $this->mCategories[$c] = $sort;
853  }
854 
860  public function setCategories( array $c ): void {
861  $this->mCategories = $c;
862  }
863 
869  public function setIndicator( $id, $content ) {
870  $this->mIndicators[$id] = $content;
871  }
872 
880  public function setEnableOOUI( $enable = false ) {
881  $this->mEnableOOUI = $enable;
882  }
883 
884  public function addLanguageLink( $t ) {
885  $this->mLanguageLinks[] = $t;
886  }
887 
891  public function addWarning( $s ) {
892  wfDeprecated( __METHOD__, '1.38' );
893  $this->mWarnings[$s] = 1;
894  }
895 
902  public function addWarningMsg( string $msg, ...$args ): void {
903  $s = wfMessage( $msg, ...$args )
904  // some callers set the title here?
905  ->inContentLanguage() // because this ends up in cache
906  ->text();
907  $this->mWarnings[$s] = 1;
908  }
909 
910  public function addOutputHook( $hook, $data = false ) {
911  $this->mOutputHooks[] = [ $hook, $data ];
912  }
913 
914  public function setNewSection( $value ) {
915  $this->mNewSection = (bool)$value;
916  }
917 
921  public function setHideNewSection( bool $value ): void {
922  $this->mHideNewSection = $value;
923  }
924 
929  public function hideNewSection( $value ) {
930  wfDeprecated( __METHOD__, '1.38' );
931  $this->setHideNewSection( (bool)$value );
932  }
933 
934  public function getHideNewSection() {
935  return (bool)$this->mHideNewSection;
936  }
937 
938  public function getNewSection() {
939  return (bool)$this->mNewSection;
940  }
941 
950  public static function isLinkInternal( $internal, $url ) {
951  return (bool)preg_match( '/^' .
952  # If server is proto relative, check also for http/https links
953  ( substr( $internal, 0, 2 ) === '//' ? '(?:https?:)?' : '' ) .
954  preg_quote( $internal, '/' ) .
955  # check for query/path/anchor or end of link in each case
956  '(?:[\?\/\#]|$)/i',
957  $url
958  );
959  }
960 
961  public function addExternalLink( $url ) {
962  # We don't register links pointing to our own server, unless... :-)
963  $config = MediaWikiServices::getInstance()->getMainConfig();
964  $server = $config->get( 'Server' );
965  $registerInternalExternals = $config->get( 'RegisterInternalExternals' );
966  # Replace unnecessary URL escape codes with the referenced character
967  # This prevents spammers from hiding links from the filters
968  $url = Parser::normalizeLinkUrl( $url );
969 
970  $registerExternalLink = true;
971  if ( !$registerInternalExternals ) {
972  $registerExternalLink = !self::isLinkInternal( $server, $url );
973  }
974  if ( $registerExternalLink ) {
975  $this->mExternalLinks[$url] = 1;
976  }
977  }
978 
985  public function addLink( LinkTarget $link, $id = null ) {
986  if ( $link->isExternal() ) {
987  // Don't record interwikis in pagelinks
988  $this->addInterwikiLink( $link );
989  return;
990  }
991  $ns = $link->getNamespace();
992  $dbk = $link->getDBkey();
993  if ( $ns === NS_MEDIA ) {
994  // Normalize this pseudo-alias if it makes it down here...
995  $ns = NS_FILE;
996  } elseif ( $ns === NS_SPECIAL ) {
997  // We don't want to record Special: links in the database, so put them in a separate place.
998  // It might actually be wise to, but we'd need to do some normalization.
999  $this->mLinksSpecial[$dbk] = 1;
1000  return;
1001  } elseif ( $dbk === '' ) {
1002  // Don't record self links - [[#Foo]]
1003  return;
1004  }
1005  if ( !isset( $this->mLinks[$ns] ) ) {
1006  $this->mLinks[$ns] = [];
1007  }
1008  if ( $id === null ) {
1009  $page = MediaWikiServices::getInstance()->getPageStore()->getPageForLink( $link );
1010  $id = $page->getId();
1011  }
1012  $this->mLinks[$ns][$dbk] = $id;
1013  }
1014 
1021  public function addImage( $name, $timestamp = null, $sha1 = null ) {
1022  $this->mImages[$name] = 1;
1023  if ( $timestamp !== null && $sha1 !== null ) {
1024  $this->mFileSearchOptions[$name] = [ 'time' => $timestamp, 'sha1' => $sha1 ];
1025  }
1026  }
1027 
1035  public function addTemplate( $link, $page_id, $rev_id ) {
1036  $ns = $link->getNamespace();
1037  $dbk = $link->getDBkey();
1038  if ( !isset( $this->mTemplates[$ns] ) ) {
1039  $this->mTemplates[$ns] = [];
1040  }
1041  $this->mTemplates[$ns][$dbk] = $page_id;
1042  if ( !isset( $this->mTemplateIds[$ns] ) ) {
1043  $this->mTemplateIds[$ns] = [];
1044  }
1045  $this->mTemplateIds[$ns][$dbk] = $rev_id; // For versioning
1046  }
1047 
1054  public function addInterwikiLink( $link ) {
1055  if ( !$link->isExternal() ) {
1056  throw new MWException( 'Non-interwiki link passed, internal parser error.' );
1057  }
1058  $prefix = $link->getInterwiki();
1059  if ( !isset( $this->mInterwikiLinks[$prefix] ) ) {
1060  $this->mInterwikiLinks[$prefix] = [];
1061  }
1062  $this->mInterwikiLinks[$prefix][$link->getDBkey()] = 1;
1063  }
1064 
1072  public function addHeadItem( $section, $tag = false ) {
1073  if ( $tag !== false ) {
1074  $this->mHeadItems[$tag] = $section;
1075  } else {
1076  $this->mHeadItems[] = $section;
1077  }
1078  }
1079 
1084  public function addModules( $modules ) {
1085  $this->mModules = array_merge( $this->mModules, (array)$modules );
1086  }
1087 
1092  public function addModuleStyles( $modules ) {
1093  $this->mModuleStyles = array_merge( $this->mModuleStyles, (array)$modules );
1094  }
1095 
1103  public function addJsConfigVars( $keys, $value = null ) {
1104  if ( is_array( $keys ) ) {
1105  foreach ( $keys as $key => $value ) {
1106  $this->mJsConfigVars[$key] = $value;
1107  }
1108  return;
1109  }
1110 
1111  $this->mJsConfigVars[$keys] = $value;
1112  }
1113 
1119  public function addOutputPageMetadata( OutputPage $out ) {
1120  $this->addModules( $out->getModules() );
1121  $this->addModuleStyles( $out->getModuleStyles() );
1122  $this->addJsConfigVars( $out->getJsConfigVars() );
1123 
1124  $this->mHeadItems = array_merge( $this->mHeadItems, $out->getHeadItemsArray() );
1125  $this->mPreventClickjacking = $this->mPreventClickjacking || $out->getPreventClickjacking();
1126  }
1127 
1147  public function addTrackingCategory( $msg, PageReference $page ) {
1148  wfDeprecated( __METHOD__, '1.38' );
1149  $trackingCategories = MediaWikiServices::getInstance()->getTrackingCategories();
1150  return $trackingCategories->addTrackingCategory( $this, $msg, $page );
1151  }
1152 
1164  public function setDisplayTitle( $text ) {
1165  $this->setTitleText( $text );
1166  $this->setPageProperty( 'displaytitle', $text );
1167  }
1168 
1177  public function getDisplayTitle() {
1178  $t = $this->getTitleText();
1179  if ( $t === '' ) {
1180  return false;
1181  }
1182  return $t;
1183  }
1184 
1191  public function setFlag( $flag ): void {
1192  $this->mFlags[$flag] = true;
1193  }
1194 
1200  public function getFlag( $flag ): bool {
1201  return isset( $this->mFlags[$flag] );
1202  }
1203 
1208  public function getAllFlags() {
1209  return array_keys( $this->mFlags );
1210  }
1211 
1218  public function setProperty( $name, $value ) {
1219  wfDeprecated( __METHOD__, '1.38' );
1220  $this->setPageProperty( $name, $value );
1221  }
1222 
1232  public function getProperty( $name ) {
1233  wfDeprecated( __METHOD__, '1.38' );
1234  return $this->getPageProperty( $name );
1235  }
1236 
1241  public function unsetProperty( $name ) {
1242  wfDeprecated( __METHOD__, '1.38' );
1243  $this->unsetPageProperty( $name );
1244  }
1245 
1250  public function getProperties() {
1251  wfDeprecated( __METHOD__, '1.38' );
1252  return $this->getPageProperties();
1253  }
1254 
1321  public function setPageProperty( string $name, $value ): void {
1322  $this->mProperties[$name] = $value;
1323  }
1324 
1334  public function getPageProperty( string $name ) {
1335  return $this->mProperties[$name] ?? false;
1336  }
1337 
1343  public function unsetPageProperty( string $name ): void {
1344  unset( $this->mProperties[$name] );
1345  }
1346 
1352  public function getPageProperties(): array {
1353  if ( !isset( $this->mProperties ) ) {
1354  $this->mProperties = [];
1355  }
1356  return $this->mProperties;
1357  }
1358 
1370  public function setOutputFlag( string $name, bool $val = true ): void {
1371  switch ( $name ) {
1372  case ParserOutputFlags::NO_GALLERY:
1373  $this->setNoGallery( $val );
1374  break;
1375 
1376  case ParserOutputFlags::ENABLE_OOUI:
1377  $this->setEnableOOUI( $val );
1378  break;
1379 
1380  case ParserOutputFlags::NO_INDEX_POLICY:
1381  case ParserOutputFlags::INDEX_POLICY:
1382  if ( !$val ) {
1383  $this->setIndexPolicy( '' );
1384  } elseif ( $name === ParserOutputFlags::INDEX_POLICY ) {
1385  $this->setIndexPolicy( 'index' );
1386  } else {
1387  $this->setIndexPolicy( 'noindex' );
1388  }
1389  break;
1390 
1391  case ParserOutputFlags::NEW_SECTION:
1392  $this->setNewSection( $val );
1393  break;
1394 
1395  case ParserOutputFlags::HIDE_NEW_SECTION:
1396  $this->setHideNewSection( $val );
1397  break;
1398 
1399  case ParserOutputFlags::PREVENT_CLICKJACKING:
1400  $this->setPreventClickjacking( $val );
1401  break;
1402 
1403  default:
1404  if ( $val ) {
1405  $this->mFlags[$name] = true;
1406  } else {
1407  unset( $this->mFlags[$name] );
1408  }
1409  break;
1410  }
1411  }
1412 
1425  public function getOutputFlag( string $name ): bool {
1426  switch ( $name ) {
1427  case ParserOutputFlags::NO_GALLERY:
1428  return $this->getNoGallery();
1429 
1430  case ParserOutputFlags::ENABLE_OOUI:
1431  return $this->getEnableOOUI();
1432 
1433  case ParserOutputFlags::INDEX_POLICY:
1434  return $this->getIndexPolicy() === 'index';
1435 
1436  case ParserOutputFlags::NO_INDEX_POLICY:
1437  return $this->getIndexPolicy() === 'noindex';
1438 
1439  case ParserOutputFlags::NEW_SECTION:
1440  return $this->getNewSection();
1441 
1442  case ParserOutputFlags::HIDE_NEW_SECTION:
1443  return $this->getHideNewSection();
1444 
1445  case ParserOutputFlags::PREVENT_CLICKJACKING:
1446  return $this->getPreventClickjacking();
1447 
1448  default:
1449  return $this->getFlag( $name );
1450 
1451  }
1452  }
1453 
1497  public function setExtensionData( $key, $value ) {
1498  if ( $value === null ) {
1499  unset( $this->mExtensionData[$key] );
1500  } else {
1501  $this->mExtensionData[$key] = $value;
1502  }
1503  }
1504 
1516  public function getExtensionData( $key ) {
1517  return $this->mExtensionData[$key] ?? null;
1518  }
1519 
1520  private static function getTimes( $clock = null ) {
1521  $ret = [];
1522  if ( !$clock || $clock === 'wall' ) {
1523  $ret['wall'] = microtime( true );
1524  }
1525  if ( !$clock || $clock === 'cpu' ) {
1526  $ru = getrusage( 0 /* RUSAGE_SELF */ );
1527  $ret['cpu'] = $ru['ru_utime.tv_sec'] + $ru['ru_utime.tv_usec'] / 1e6;
1528  $ret['cpu'] += $ru['ru_stime.tv_sec'] + $ru['ru_stime.tv_usec'] / 1e6;
1529  }
1530  return $ret;
1531  }
1532 
1537  public function resetParseStartTime() {
1538  $this->mParseStartTime = self::getTimes();
1539  }
1540 
1552  public function getTimeSinceStart( $clock ) {
1553  if ( !isset( $this->mParseStartTime[$clock] ) ) {
1554  return null;
1555  }
1556 
1557  $end = self::getTimes( $clock );
1558  return $end[$clock] - $this->mParseStartTime[$clock];
1559  }
1560 
1580  public function setLimitReportData( $key, $value ) {
1581  $this->mLimitReportData[$key] = $value;
1582 
1583  if ( is_array( $value ) ) {
1584  if ( array_keys( $value ) === [ 0, 1 ]
1585  && is_numeric( $value[0] )
1586  && is_numeric( $value[1] )
1587  ) {
1588  $data = [ 'value' => $value[0], 'limit' => $value[1] ];
1589  } else {
1590  $data = $value;
1591  }
1592  } else {
1593  $data = $value;
1594  }
1595 
1596  if ( strpos( $key, '-' ) ) {
1597  list( $ns, $name ) = explode( '-', $key, 2 );
1598  $this->mLimitReportJSData[$ns][$name] = $data;
1599  } else {
1600  $this->mLimitReportJSData[$key] = $data;
1601  }
1602  }
1603 
1604  private function renderDebugInfo(): string {
1605  $text = '';
1606 
1607  $limitReportData = $this->getLimitReportData();
1608  // If nothing set it, we can't get it.
1609  if ( $limitReportData ) {
1610  $limitReport = "NewPP limit report\n";
1611 
1612  if ( array_key_exists( 'cachereport-origin', $limitReportData ) ) {
1613  $limitReport .= "Parsed by {$limitReportData['cachereport-origin']}\n";
1614  }
1615 
1616  if ( array_key_exists( 'cachereport-timestamp', $limitReportData ) ) {
1617  $limitReport .= "Cached time: {$limitReportData['cachereport-timestamp']}\n";
1618  }
1619 
1620  if ( array_key_exists( 'cachereport-ttl', $limitReportData ) ) {
1621  $limitReport .= "Cache expiry: {$limitReportData['cachereport-ttl']}\n";
1622  }
1623 
1624  if ( array_key_exists( 'cachereport-transientcontent', $limitReportData ) ) {
1625  $transient = $limitReportData['cachereport-transientcontent'] ? 'true' : 'false';
1626  $limitReport .= "Reduced expiry: $transient\n";
1627  }
1628 
1629  // TODO: flags should go into limit report too.
1630  $limitReport .= 'Complications: [' . implode( ', ', $this->getAllFlags() ) . "]\n";
1631 
1632  foreach ( $limitReportData as $key => $value ) {
1633  if ( in_array( $key, [
1634  'cachereport-origin',
1635  'cachereport-timestamp',
1636  'cachereport-ttl',
1637  'cachereport-transientcontent',
1638  'limitreport-timingprofile'
1639  ] ) ) {
1640  // These keys are processed separately.
1641  continue;
1642  }
1643  if ( Hooks::runner()->onParserLimitReportFormat(
1644  $key, $value, $limitReport, false, false )
1645  ) {
1646  $keyMsg = wfMessage( $key )->inLanguage( 'en' )->useDatabase( false );
1647  $valueMsg = wfMessage( [ "$key-value-text", "$key-value" ] )
1648  ->inLanguage( 'en' )->useDatabase( false );
1649  if ( !$valueMsg->exists() ) {
1650  $valueMsg = new RawMessage( '$1' );
1651  }
1652  if ( !$keyMsg->isDisabled() && !$valueMsg->isDisabled() ) {
1653  $valueMsg->params( $value );
1654  $limitReport .= "{$keyMsg->text()}: {$valueMsg->text()}\n";
1655  }
1656  }
1657  }
1658  // Since we're not really outputting HTML, decode the entities and
1659  // then re-encode the things that need hiding inside HTML comments.
1660  $limitReport = htmlspecialchars_decode( $limitReport );
1661 
1662  // Sanitize for comment. Note '‐' in the replacement is U+2010,
1663  // which looks much like the problematic '-'.
1664  $limitReport = str_replace( [ '-', '&' ], [ '‐', '&amp;' ], $limitReport );
1665  $text = "\n<!-- \n$limitReport-->\n";
1666 
1667  $profileReport = $limitReportData['limitreport-timingprofile'] ?? null;
1668  if ( $profileReport ) {
1669  $text .= "<!--\nTransclusion expansion time report (%,ms,calls,template)\n";
1670  $text .= implode( "\n", $profileReport ) . "\n-->\n";
1671  }
1672  }
1673 
1674  if ( $this->mCacheMessage ) {
1675  $text .= "\n<!-- $this->mCacheMessage\n -->\n";
1676  }
1677 
1678  return $text;
1679  }
1680 
1697  public function hasReducedExpiry(): bool {
1698  $parserCacheExpireTime = MediaWikiServices::getInstance()->getMainConfig()->get( 'ParserCacheExpireTime' );
1699 
1700  return $this->getCacheExpiry() < $parserCacheExpireTime;
1701  }
1702 
1709  public function hasDynamicContent() {
1710  wfDeprecated( __METHOD__, '1.38' );
1711  return $this->hasReducedExpiry();
1712  }
1713 
1720  public function setPreventClickjacking( bool $flag ) {
1721  $this->mPreventClickjacking = $flag;
1722  }
1723 
1730  public function getPreventClickjacking(): bool {
1732  }
1733 
1743  public function preventClickjacking( $flag ) {
1744  wfDeprecated( __METHOD__, '1.38' );
1745  $old = $this->getPreventClickjacking();
1746  if ( $flag !== null ) {
1747  $this->setPreventClickjacking( $flag );
1748  }
1749  return $old;
1750  }
1751 
1758  public function updateRuntimeAdaptiveExpiry( $ttl ) {
1759  $this->mMaxAdaptiveExpiry = min( $ttl, $this->mMaxAdaptiveExpiry );
1760  $this->updateCacheExpiry( $ttl );
1761  }
1762 
1772  public function addExtraCSPDefaultSrc( $src ) {
1773  $this->mExtraDefaultSrcs[] = $src;
1774  }
1775 
1782  public function addExtraCSPStyleSrc( $src ) {
1783  $this->mExtraStyleSrcs[] = $src;
1784  }
1785 
1794  public function addExtraCSPScriptSrc( $src ) {
1795  $this->mExtraScriptSrcs[] = $src;
1796  }
1797 
1803  public function finalizeAdaptiveCacheExpiry() {
1804  if ( is_infinite( $this->mMaxAdaptiveExpiry ) ) {
1805  return; // not set
1806  }
1807 
1808  $runtime = $this->getTimeSinceStart( 'wall' );
1809  if ( is_float( $runtime ) ) {
1810  $slope = ( self::SLOW_AR_TTL - self::FAST_AR_TTL )
1811  / ( self::PARSE_SLOW_SEC - self::PARSE_FAST_SEC );
1812  // SLOW_AR_TTL = PARSE_SLOW_SEC * $slope + $point
1813  $point = self::SLOW_AR_TTL - self::PARSE_SLOW_SEC * $slope;
1814 
1815  $adaptiveTTL = min(
1816  max( $slope * $runtime + $point, self::MIN_AR_TTL ),
1817  $this->mMaxAdaptiveExpiry
1818  );
1819  $this->updateCacheExpiry( $adaptiveTTL );
1820  }
1821  }
1822 
1823  public function __sleep() {
1824  return array_filter( array_keys( get_object_vars( $this ) ),
1825  static function ( $field ) {
1826  if ( $field === 'mParseStartTime' ) {
1827  return false;
1828  }
1829  // Unserializing unknown private fields in HHVM causes
1830  // member variables with nulls in their names (T229366)
1831  return strpos( $field, "\0" ) === false;
1832  }
1833  );
1834  }
1835 
1844  $this->mOutputHooks = self::mergeList( $this->mOutputHooks, $source->getOutputHooks() );
1845  $this->mWarnings = self::mergeMap( $this->mWarnings, $source->mWarnings ); // don't use getter
1846  $this->mTimestamp = $this->useMaxValue( $this->mTimestamp, $source->getTimestamp() );
1847 
1848  foreach ( self::SPECULATIVE_FIELDS as $field ) {
1849  if ( $this->$field && $source->$field && $this->$field !== $source->$field ) {
1850  wfLogWarning( __METHOD__ . ": inconsistent '$field' properties!" );
1851  }
1852  $this->$field = $this->useMaxValue( $this->$field, $source->$field );
1853  }
1854 
1855  $this->mParseStartTime = $this->useEachMinValue(
1856  $this->mParseStartTime,
1857  $source->mParseStartTime
1858  );
1859 
1860  $this->mFlags = self::mergeMap( $this->mFlags, $source->mFlags );
1861  $this->mParseUsedOptions = self::mergeMap( $this->mParseUsedOptions, $source->mParseUsedOptions );
1862 
1863  // TODO: maintain per-slot limit reports!
1864  if ( empty( $this->mLimitReportData ) ) {
1865  $this->mLimitReportData = $source->mLimitReportData;
1866  }
1867  if ( empty( $this->mLimitReportJSData ) ) {
1868  $this->mLimitReportJSData = $source->mLimitReportJSData;
1869  }
1870  }
1871 
1880  // HTML and HTTP
1881  $this->mHeadItems = self::mergeMixedList( $this->mHeadItems, $source->getHeadItems() );
1882  $this->mModules = self::mergeList( $this->mModules, $source->getModules() );
1883  $this->mModuleStyles = self::mergeList( $this->mModuleStyles, $source->getModuleStyles() );
1884  $this->mJsConfigVars = self::mergeMap( $this->mJsConfigVars, $source->getJsConfigVars() );
1885  $this->mMaxAdaptiveExpiry = min( $this->mMaxAdaptiveExpiry, $source->mMaxAdaptiveExpiry );
1886  $this->mExtraStyleSrcs = self::mergeList(
1887  $this->mExtraStyleSrcs,
1888  $source->getExtraCSPStyleSrcs()
1889  );
1890  $this->mExtraScriptSrcs = self::mergeList(
1891  $this->mExtraScriptSrcs,
1892  $source->getExtraCSPScriptSrcs()
1893  );
1894  $this->mExtraDefaultSrcs = self::mergeList(
1895  $this->mExtraDefaultSrcs,
1896  $source->getExtraCSPDefaultSrcs()
1897  );
1898 
1899  // "noindex" always wins!
1900  if ( $this->mIndexPolicy === 'noindex' || $source->mIndexPolicy === 'noindex' ) {
1901  $this->mIndexPolicy = 'noindex';
1902  } elseif ( $this->mIndexPolicy !== 'index' ) {
1903  $this->mIndexPolicy = $source->mIndexPolicy;
1904  }
1905 
1906  // Skin control
1907  $this->mNewSection = $this->mNewSection || $source->getNewSection();
1908  $this->mHideNewSection = $this->mHideNewSection || $source->getHideNewSection();
1909  $this->mNoGallery = $this->mNoGallery || $source->getNoGallery();
1910  $this->mEnableOOUI = $this->mEnableOOUI || $source->getEnableOOUI();
1911  $this->mPreventClickjacking = $this->mPreventClickjacking || $source->getPreventClickjacking();
1912 
1913  // TODO: we'll have to be smarter about this!
1914  $this->mSections = array_merge( $this->mSections, $source->getSections() );
1915  $this->mTOCHTML .= $source->mTOCHTML;
1916 
1917  // XXX: we don't want to concatenate title text, so first write wins.
1918  // We should use the first *modified* title text, but we don't have the original to check.
1919  if ( $this->mTitleText === null || $this->mTitleText === '' ) {
1920  $this->mTitleText = $source->mTitleText;
1921  }
1922 
1923  // class names are stored in array keys
1924  $this->mWrapperDivClasses = self::mergeMap(
1925  $this->mWrapperDivClasses,
1926  $source->mWrapperDivClasses
1927  );
1928 
1929  // NOTE: last write wins, same as within one ParserOutput
1930  $this->mIndicators = self::mergeMap( $this->mIndicators, $source->getIndicators() );
1931 
1932  // NOTE: include extension data in "tracking meta data" as well as "html meta data"!
1933  // TODO: add a $mergeStrategy parameter to setExtensionData to allow different
1934  // kinds of extension data to be merged in different ways.
1935  $this->mExtensionData = self::mergeMap(
1936  $this->mExtensionData,
1937  $source->mExtensionData
1938  );
1939  }
1940 
1949  $this->mLanguageLinks = self::mergeList( $this->mLanguageLinks, $source->getLanguageLinks() );
1950  $this->mCategories = self::mergeMap( $this->mCategories, $source->getCategories() );
1951  $this->mLinks = self::merge2D( $this->mLinks, $source->getLinks() );
1952  $this->mTemplates = self::merge2D( $this->mTemplates, $source->getTemplates() );
1953  $this->mTemplateIds = self::merge2D( $this->mTemplateIds, $source->getTemplateIds() );
1954  $this->mImages = self::mergeMap( $this->mImages, $source->getImages() );
1955  $this->mFileSearchOptions = self::mergeMap(
1956  $this->mFileSearchOptions,
1957  $source->getFileSearchOptions()
1958  );
1959  $this->mExternalLinks = self::mergeMap( $this->mExternalLinks, $source->getExternalLinks() );
1960  $this->mInterwikiLinks = self::merge2D(
1961  $this->mInterwikiLinks,
1962  $source->getInterwikiLinks()
1963  );
1964 
1965  // TODO: add a $mergeStrategy parameter to setPageProperty to allow different
1966  // kinds of properties to be merged in different ways.
1967  $this->mProperties = self::mergeMap( $this->mProperties, $source->getPageProperties() );
1968 
1969  // NOTE: include extension data in "tracking meta data" as well as "html meta data"!
1970  // TODO: add a $mergeStrategy parameter to setExtensionData to allow different
1971  // kinds of extension data to be merged in different ways.
1972  $this->mExtensionData = self::mergeMap(
1973  $this->mExtensionData,
1974  $source->mExtensionData
1975  );
1976  }
1977 
1978  private static function mergeMixedList( array $a, array $b ) {
1979  return array_unique( array_merge( $a, $b ), SORT_REGULAR );
1980  }
1981 
1982  private static function mergeList( array $a, array $b ) {
1983  return array_values( array_unique( array_merge( $a, $b ), SORT_REGULAR ) );
1984  }
1985 
1986  private static function mergeMap( array $a, array $b ) {
1987  return array_replace( $a, $b );
1988  }
1989 
1990  private static function merge2D( array $a, array $b ) {
1991  $values = [];
1992  $keys = array_merge( array_keys( $a ), array_keys( $b ) );
1993 
1994  foreach ( $keys as $k ) {
1995  if ( empty( $a[$k] ) ) {
1996  $values[$k] = $b[$k];
1997  } elseif ( empty( $b[$k] ) ) {
1998  $values[$k] = $a[$k];
1999  } elseif ( is_array( $a[$k] ) && is_array( $b[$k] ) ) {
2000  $values[$k] = array_replace( $a[$k], $b[$k] );
2001  } else {
2002  $values[$k] = $b[$k];
2003  }
2004  }
2005 
2006  return $values;
2007  }
2008 
2009  private static function useEachMinValue( array $a, array $b ) {
2010  $values = [];
2011  $keys = array_merge( array_keys( $a ), array_keys( $b ) );
2012 
2013  foreach ( $keys as $k ) {
2014  if ( is_array( $a[$k] ?? null ) && is_array( $b[$k] ?? null ) ) {
2015  $values[$k] = self::useEachMinValue( $a[$k], $b[$k] );
2016  } else {
2017  $values[$k] = self::useMinValue( $a[$k] ?? null, $b[$k] ?? null );
2018  }
2019  }
2020 
2021  return $values;
2022  }
2023 
2024  private static function useMinValue( $a, $b ) {
2025  if ( $a === null ) {
2026  return $b;
2027  }
2028 
2029  if ( $b === null ) {
2030  return $a;
2031  }
2032 
2033  return min( $a, $b );
2034  }
2035 
2036  private static function useMaxValue( $a, $b ) {
2037  if ( $a === null ) {
2038  return $b;
2039  }
2040 
2041  if ( $b === null ) {
2042  return $a;
2043  }
2044 
2045  return max( $a, $b );
2046  }
2047 
2054  protected function toJsonArray(): array {
2055  $data = [
2056  'Text' => $this->mText,
2057  'LanguageLinks' => $this->mLanguageLinks,
2058  'Categories' => $this->mCategories,
2059  'Indicators' => $this->mIndicators,
2060  'TitleText' => $this->mTitleText,
2061  'Links' => $this->mLinks,
2062  'LinksSpecial' => $this->mLinksSpecial,
2063  'Templates' => $this->mTemplates,
2064  'TemplateIds' => $this->mTemplateIds,
2065  'Images' => $this->mImages,
2066  'FileSearchOptions' => $this->mFileSearchOptions,
2067  'ExternalLinks' => $this->mExternalLinks,
2068  'InterwikiLinks' => $this->mInterwikiLinks,
2069  'NewSection' => $this->mNewSection,
2070  'HideNewSection' => $this->mHideNewSection,
2071  'NoGallery' => $this->mNoGallery,
2072  'HeadItems' => $this->mHeadItems,
2073  'Modules' => $this->mModules,
2074  'ModuleStyles' => $this->mModuleStyles,
2075  'JsConfigVars' => $this->mJsConfigVars,
2076  'OutputHooks' => $this->mOutputHooks,
2077  'Warnings' => $this->mWarnings,
2078  'Sections' => $this->mSections,
2079  'Properties' => self::detectAndEncodeBinary( $this->mProperties ),
2080  'TOCHTML' => $this->mTOCHTML,
2081  'Timestamp' => $this->mTimestamp,
2082  'EnableOOUI' => $this->mEnableOOUI,
2083  'IndexPolicy' => $this->mIndexPolicy,
2084  // may contain arbitrary structures!
2085  'ExtensionData' => $this->mExtensionData,
2086  'LimitReportData' => $this->mLimitReportData,
2087  'LimitReportJSData' => $this->mLimitReportJSData,
2088  'CacheMessage' => $this->mCacheMessage,
2089  'ParseStartTime' => $this->mParseStartTime,
2090  'PreventClickjacking' => $this->mPreventClickjacking,
2091  'ExtraScriptSrcs' => $this->mExtraScriptSrcs,
2092  'ExtraDefaultSrcs' => $this->mExtraDefaultSrcs,
2093  'ExtraStyleSrcs' => $this->mExtraStyleSrcs,
2094  'Flags' => $this->mFlags,
2095  'SpeculativeRevId' => $this->mSpeculativeRevId,
2096  'SpeculativePageIdUsed' => $this->speculativePageIdUsed,
2097  'RevisionTimestampUsed' => $this->revisionTimestampUsed,
2098  'RevisionUsedSha1Base36' => $this->revisionUsedSha1Base36,
2099  'WrapperDivClasses' => $this->mWrapperDivClasses,
2100  ];
2101 
2102  // Fill in missing fields from parents. Array addition does not override existing fields.
2103  $data += parent::toJsonArray();
2104 
2105  // TODO: make more fields optional!
2106 
2107  if ( $this->mMaxAdaptiveExpiry !== INF ) {
2108  // NOTE: JSON can't encode infinity!
2109  $data['MaxAdaptiveExpiry'] = $this->mMaxAdaptiveExpiry;
2110  }
2111 
2112  return $data;
2113  }
2114 
2115  public static function newFromJsonArray( JsonUnserializer $unserializer, array $json ) {
2116  $parserOutput = new ParserOutput();
2117  $parserOutput->initFromJson( $unserializer, $json );
2118  return $parserOutput;
2119  }
2120 
2126  protected function initFromJson( JsonUnserializer $unserializer, array $jsonData ) {
2127  parent::initFromJson( $unserializer, $jsonData );
2128 
2129  $this->mText = $jsonData['Text'];
2130  $this->mLanguageLinks = $jsonData['LanguageLinks'];
2131  $this->mCategories = $jsonData['Categories'];
2132  $this->mIndicators = $jsonData['Indicators'];
2133  $this->mTitleText = $jsonData['TitleText'];
2134  $this->mLinks = $jsonData['Links'];
2135  $this->mLinksSpecial = $jsonData['LinksSpecial'];
2136  $this->mTemplates = $jsonData['Templates'];
2137  $this->mTemplateIds = $jsonData['TemplateIds'];
2138  $this->mImages = $jsonData['Images'];
2139  $this->mFileSearchOptions = $jsonData['FileSearchOptions'];
2140  $this->mExternalLinks = $jsonData['ExternalLinks'];
2141  $this->mInterwikiLinks = $jsonData['InterwikiLinks'];
2142  $this->mNewSection = $jsonData['NewSection'];
2143  $this->mHideNewSection = $jsonData['HideNewSection'];
2144  $this->mNoGallery = $jsonData['NoGallery'];
2145  $this->mHeadItems = $jsonData['HeadItems'];
2146  $this->mModules = $jsonData['Modules'];
2147  $this->mModuleStyles = $jsonData['ModuleStyles'];
2148  $this->mJsConfigVars = $jsonData['JsConfigVars'];
2149  $this->mOutputHooks = $jsonData['OutputHooks'];
2150  $this->mWarnings = $jsonData['Warnings'];
2151  $this->mSections = $jsonData['Sections'];
2152  $this->mProperties = self::detectAndDecodeBinary( $jsonData['Properties'] );
2153  $this->mTOCHTML = $jsonData['TOCHTML'];
2154  $this->mTimestamp = $jsonData['Timestamp'];
2155  $this->mEnableOOUI = $jsonData['EnableOOUI'];
2156  $this->mIndexPolicy = $jsonData['IndexPolicy'];
2157  $this->mExtensionData = $unserializer->unserializeArray( $jsonData['ExtensionData'] ?? [] );
2158  $this->mLimitReportData = $jsonData['LimitReportData'];
2159  $this->mLimitReportJSData = $jsonData['LimitReportJSData'];
2160  $this->mCacheMessage = $jsonData['CacheMessage'] ?? '';
2161  $this->mParseStartTime = $jsonData['ParseStartTime'];
2162  $this->mPreventClickjacking = $jsonData['PreventClickjacking'];
2163  $this->mExtraScriptSrcs = $jsonData['ExtraScriptSrcs'];
2164  $this->mExtraDefaultSrcs = $jsonData['ExtraDefaultSrcs'];
2165  $this->mExtraStyleSrcs = $jsonData['ExtraStyleSrcs'];
2166  $this->mFlags = $jsonData['Flags'];
2167  $this->mSpeculativeRevId = $jsonData['SpeculativeRevId'];
2168  $this->speculativePageIdUsed = $jsonData['SpeculativePageIdUsed'];
2169  $this->revisionTimestampUsed = $jsonData['RevisionTimestampUsed'];
2170  $this->revisionUsedSha1Base36 = $jsonData['RevisionUsedSha1Base36'];
2171  $this->mWrapperDivClasses = $jsonData['WrapperDivClasses'];
2172  $this->mMaxAdaptiveExpiry = $jsonData['MaxAdaptiveExpiry'] ?? INF;
2173  }
2174 
2184  private static function detectAndEncodeBinary( array $properties ) {
2185  foreach ( $properties as $key => $value ) {
2186  if ( is_string( $value ) ) {
2187  if ( !mb_detect_encoding( $value, 'UTF-8', true ) ) {
2188  $properties[$key] = [
2189  '_type_' => 'string',
2190  '_encoding_' => 'base64',
2191  '_data_' => base64_encode( $value ),
2192  ];
2193  }
2194  }
2195  }
2196 
2197  return $properties;
2198  }
2199 
2208  private static function detectAndDecodeBinary( array $properties ) {
2209  foreach ( $properties as $key => $value ) {
2210  if ( is_array( $value ) && isset( $value['_encoding_'] ) ) {
2211  if ( $value['_encoding_'] === 'base64' ) {
2212  $properties[$key] = base64_decode( $value['_data_'] );
2213  }
2214  }
2215  }
2216 
2217  return $properties;
2218  }
2219 
2220  public function __wakeup() {
2221  // Backwards compatibility, pre 1.36
2222  $priorAccessedOptions = $this->getGhostFieldValue( 'mAccessedOptions' );
2223  if ( $priorAccessedOptions ) {
2224  $this->mParseUsedOptions = $priorAccessedOptions;
2225  }
2226  }
2227 
2228  public function __get( $name ) {
2229  if ( property_exists( get_called_class(), $name ) ) {
2230  // Direct access to a public property, deprecated.
2231  wfDeprecatedMsg( "ParserOutput::{$name} public read access deprecated", '1.38' );
2232  return $this->$name;
2233  } elseif ( property_exists( $this, $name ) ) {
2234  // Dynamic property access, deprecated.
2235  wfDeprecatedMsg( "ParserOutput::{$name} dynamic property read access deprecated", '1.38' );
2236  return $this->$name;
2237  } else {
2238  trigger_error( "Inaccessible property via __set(): $name" );
2239  return null;
2240  }
2241  }
2242 
2243  public function __set( $name, $value ) {
2244  if ( property_exists( get_called_class(), $name ) ) {
2245  // Direct access to a public property, deprecated.
2246  wfDeprecatedMsg( "ParserOutput::$name public write access deprecated", '1.38' );
2247  $this->$name = $value;
2248  } else {
2249  // Dynamic property access, deprecated.
2250  wfDeprecatedMsg( "ParserOutput::$name dynamic property write access deprecated", '1.38' );
2251  $this->$name = $value;
2252  }
2253  }
2254 }
ParserOutput\$mImages
array $mImages
DB keys of the images used, in the array key only.
Definition: ParserOutput.php:106
ParserOutput\$mWrapperDivClasses
$mWrapperDivClasses
string CSS classes to use for the wrapping div, stored in the array keys.
Definition: ParserOutput.php:266
ParserOutput\addCacheMessage
addCacheMessage(string $msg)
Adds a comment notice about cache state to the text of the page.
Definition: ParserOutput.php:529
ParserOutput\addOutputPageMetadata
addOutputPageMetadata(OutputPage $out)
Copy items from the OutputPage object into this one.
Definition: ParserOutput.php:1119
MediaWiki\Json\JsonUnserializer
Definition: JsonUnserializer.php:33
ParserOutput\getEnableOOUI
getEnableOOUI()
Definition: ParserOutput.php:779
ParserOutput\mergeMap
static mergeMap(array $a, array $b)
Definition: ParserOutput.php:1986
ParserOutput\$mEnableOOUI
bool $mEnableOOUI
Whether OOUI should be enabled.
Definition: ParserOutput.php:193
ParserOutput\$mWarnings
array $mWarnings
Warning text to be returned to the user.
Definition: ParserOutput.php:168
ParserOutput\$mJsConfigVars
array $mJsConfigVars
JavaScript config variable for mw.config combined with this page.
Definition: ParserOutput.php:157
CacheTime\getCacheExpiry
getCacheExpiry()
Returns the number of seconds after which this object should expire.
Definition: CacheTime.php:143
ParserOutput\$mFileSearchOptions
array $mFileSearchOptions
DB keys of the images used mapped to sha1 and MW timestamp.
Definition: ParserOutput.php:111
Title\newFromText
static newFromText( $text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
Definition: Title.php:377
ParserOutput\setTitleText
setTitleText( $t)
Definition: ParserOutput.php:826
ParserOutput
Definition: ParserOutput.php:35
MediaWiki\Json\JsonUnserializableTrait
trait JsonUnserializableTrait
Definition: JsonUnserializableTrait.php:24
ParserOutput\setSpeculativeRevIdUsed
setSpeculativeRevIdUsed( $id)
Definition: ParserOutput.php:565
ParserOutput\SUPPORTS_UNWRAP_TRANSFORM
const SUPPORTS_UNWRAP_TRANSFORM
Definition: ParserOutput.php:50
CacheTime
Parser cache specific expiry check.
Definition: CacheTime.php:36
ParserOutput\resetParseStartTime
resetParseStartTime()
Resets the parse start timestamps for future calls to getTimeSinceStart()
Definition: ParserOutput.php:1537
ParserOutput\setDisplayTitle
setDisplayTitle( $text)
Override the title to be used for display.
Definition: ParserOutput.php:1164
MediaWiki\Json\JsonUnserializable
Definition: JsonUnserializable.php:38
ParserOutput\$mLanguageLinks
array $mLanguageLinks
List of the full text of language links, in the order they appear.
Definition: ParserOutput.php:61
ParserOutput\setTimestamp
setTimestamp( $timestamp)
Definition: ParserOutput.php:842
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:203
ParserOutput\mergeMixedList
static mergeMixedList(array $a, array $b)
Definition: ParserOutput.php:1978
ParserOutput\addExtraCSPScriptSrc
addExtraCSPScriptSrc( $src)
Add an extra value to Content-Security-Policy script-src directive.
Definition: ParserOutput.php:1794
ParserOutput\setLimitReportData
setLimitReportData( $key, $value)
Sets parser limit report data for a key.
Definition: ParserOutput.php:1580
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:1496
ParserOutput\merge2D
static merge2D(array $a, array $b)
Definition: ParserOutput.php:1990
ParserOutput\addWrapperDivClass
addWrapperDivClass( $class)
Add a CSS class to use for the wrapping div.
Definition: ParserOutput.php:538
ParserOutput\$mLimitReportJSData
array $mLimitReportJSData
Parser limit report data for JSON.
Definition: ParserOutput.php:211
Parser\ParserOutputFlags
Definition: ParserOutputFlags.php:41
ParserOutput\$mModules
array $mModules
Modules to be loaded by ResourceLoader.
Definition: ParserOutput.php:147
ParserOutput\__sleep
__sleep()
Definition: ParserOutput.php:1823
ParserOutput\setNewSection
setNewSection( $value)
Definition: ParserOutput.php:914
ParserOutput\getModules
getModules()
Definition: ParserOutput.php:732
ParserOutput\getImages
& getImages()
Definition: ParserOutput.php:708
ParserOutput\addModules
addModules( $modules)
Definition: ParserOutput.php:1084
ParserOutput\getPreventClickjacking
getPreventClickjacking()
Get the prevent-clickjacking flag.
Definition: ParserOutput.php:1730
ParserOutput\MIN_AR_TTL
const MIN_AR_TTL
Definition: ParserOutput.php:281
ParserOutput\$mLinksSpecial
array $mLinksSpecial
Keys are DBKs for the links to special pages in the document.
Definition: ParserOutput.php:89
ParserOutput\$mOutputHooks
array $mOutputHooks
Hook tags as per $wgParserOutputHooks.
Definition: ParserOutput.php:162
ParserOutput\setIndicator
setIndicator( $id, $content)
Definition: ParserOutput.php:869
ParserOutput\getJsConfigVars
getJsConfigVars()
Definition: ParserOutput.php:744
wfUrlencode
wfUrlencode( $s)
We want some things to be included as literal characters in our title URLs for prettiness,...
Definition: GlobalFunctions.php:292
ParserOutput\addLink
addLink(LinkTarget $link, $id=null)
Record a local or interwiki inline link for saving in future link tables.
Definition: ParserOutput.php:985
ParserOutput\mergeTrackingMetaDataFrom
mergeTrackingMetaDataFrom(ParserOutput $source)
Merges dependency tracking metadata such as backlinks, images used, and extension data from $source i...
Definition: ParserOutput.php:1948
ParserOutput\addExtraCSPStyleSrc
addExtraCSPStyleSrc( $src)
Add an extra value to Content-Security-Policy style-src directive.
Definition: ParserOutput.php:1782
OutputPage\getModuleStyles
getModuleStyles( $filter=false, $position=null)
Get the list of style-only modules to load on this page.
Definition: OutputPage.php:578
ParserOutput\unsetProperty
unsetProperty( $name)
Definition: ParserOutput.php:1241
ParserOutput\setFlag
setFlag( $flag)
Attach a flag to the output so that it can be checked later to handle special cases.
Definition: ParserOutput.php:1191
ParserOutput\hideNewSection
hideNewSection( $value)
Definition: ParserOutput.php:929
wfMessage
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
Definition: GlobalFunctions.php:1167
ParserOutput\$mMaxAdaptiveExpiry
int $mMaxAdaptiveExpiry
Upper bound of expiry based on parse duration.
Definition: ParserOutput.php:269
ParserOutput\__construct
__construct( $text='', $languageLinks=[], $categoryLinks=[], $unused=false, $titletext='')
Definition: ParserOutput.php:292
ParserOutput\toJsonArray
toJsonArray()
Returns a JSON serializable structure representing this ParserOutput instance.
Definition: ParserOutput.php:2054
wfLogWarning
wfLogWarning( $msg, $callerOffset=1, $level=E_USER_WARNING)
Send a warning as a PHP error and the debug log.
Definition: GlobalFunctions.php:1056
ParserOutput\EDITSECTION_REGEX
const EDITSECTION_REGEX
Definition: ParserOutput.php:271
ParserOutput\PARSE_SLOW_SEC
const PARSE_SLOW_SEC
Definition: ParserOutput.php:278
MediaWiki\Linker\LinkTarget\isExternal
isExternal()
Whether this LinkTarget has an interwiki component.
ParserOutput\getHeadItems
getHeadItems()
Definition: ParserOutput.php:728
ParserOutput\hasReducedExpiry
hasReducedExpiry()
Check whether the cache TTL was lowered from the site default.
Definition: ParserOutput.php:1697
ParserOutput\PARSE_FAST_SEC
const PARSE_FAST_SEC
Definition: ParserOutput.php:277
ParserOutput\addTrackingCategory
addTrackingCategory( $msg, PageReference $page)
Add a tracking category, getting the title from a system message, or print a debug message if the tit...
Definition: ParserOutput.php:1147
Page\PageReference
Interface for objects (potentially) representing a page that can be viewable and linked to on a wiki.
Definition: PageReference.php:49
ParserOutput\setSpeculativePageIdUsed
setSpeculativePageIdUsed( $id)
Definition: ParserOutput.php:581
ParserOutput\getProperties
getProperties()
Definition: ParserOutput.php:1250
ParserOutput\mergeList
static mergeList(array $a, array $b)
Definition: ParserOutput.php:1982
ParserOutput\__get
__get( $name)
Definition: ParserOutput.php:2228
ParserOutput\__set
__set( $name, $value)
Definition: ParserOutput.php:2243
ParserOutput\$mProperties
array $mProperties
Name/value pairs to be cached in the DB.
Definition: ParserOutput.php:178
ParserOutput\getOutputFlag
getOutputFlag(string $name)
Provides a uniform interface to various boolean flags stored in the ParserOutput.
Definition: ParserOutput.php:1425
NS_SPECIAL
const NS_SPECIAL
Definition: Defines.php:53
ParserOutput\getModuleStyles
getModuleStyles()
Definition: ParserOutput.php:736
ParserOutput\renderDebugInfo
renderDebugInfo()
Definition: ParserOutput.php:1604
ParserOutput\$mHeadItems
array $mHeadItems
Items to put in the <head> section.
Definition: ParserOutput.php:142
ParserOutput\$mTimestamp
string $mTimestamp
Timestamp of the revision.
Definition: ParserOutput.php:188
ParserOutput\getExtraCSPDefaultSrcs
getExtraCSPDefaultSrcs()
Get extra Content-Security-Policy 'default-src' directives.
Definition: ParserOutput.php:788
MediaWiki\Linker\LinkTarget\getNamespace
getNamespace()
Get the namespace index.
ParserOutput\setPreventClickjacking
setPreventClickjacking(bool $flag)
Set the prevent-clickjacking flag.
Definition: ParserOutput.php:1720
ParserOutput\addExtraCSPDefaultSrc
addExtraCSPDefaultSrc( $src)
Add an extra value to Content-Security-Policy default-src directive.
Definition: ParserOutput.php:1772
ParserOutput\getLimitReportJSData
getLimitReportJSData()
Definition: ParserOutput.php:775
wfDeprecatedMsg
wfDeprecatedMsg( $msg, $version=false, $component=false, $callerOffset=2)
Log a deprecation warning with arbitrary message text.
Definition: GlobalFunctions.php:1028
MWException
MediaWiki exception.
Definition: MWException.php:29
OutputPage\getModules
getModules( $filter=false, $position=null, $param='mModules', $type=ResourceLoaderModule::TYPE_COMBINED)
Get the list of modules to include on this page.
Definition: OutputPage.php:553
ParserOutput\getCategoryLinks
getCategoryLinks()
Return the names of the categories on this page.
Definition: ParserOutput.php:649
wfDeprecated
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that a deprecated feature was used.
Definition: GlobalFunctions.php:997
MediaWiki\Logger\LoggerFactory
PSR-3 logger instance factory.
Definition: LoggerFactory.php:45
ParserOutput\setRevisionUsedSha1Base36
setRevisionUsedSha1Base36( $hash)
Definition: ParserOutput.php:613
ParserOutput\$mLinks
int[][] $mLinks
2-D map of NS/DBK to ID for the links in the document.
Definition: ParserOutput.php:83
ParserOutput\getFlag
getFlag( $flag)
Definition: ParserOutput.php:1200
ParserOutput\getTimestamp
getTimestamp()
Definition: ParserOutput.php:767
ParserOutput\isLinkInternal
static isLinkInternal( $internal, $url)
Checks, if a url is pointing to the own server.
Definition: ParserOutput.php:950
ParserOutput\addExternalLink
addExternalLink( $url)
Definition: ParserOutput.php:961
ParserOutput\$mExtraDefaultSrcs
array $mExtraDefaultSrcs
Extra default-src for CSP [Everything but script and style].
Definition: ParserOutput.php:234
ParserOutput\getInterwikiLinks
getInterwikiLinks()
Definition: ParserOutput.php:640
ParserOutput\$mLimitReportData
array $mLimitReportData
Parser limit report data.
Definition: ParserOutput.php:208
ParserOutput\mergeHtmlMetaDataFrom
mergeHtmlMetaDataFrom(ParserOutput $source)
Merges HTML metadata such as head items, JS config vars, and HTTP cache control info from $source int...
Definition: ParserOutput.php:1879
ParserOutput\updateRuntimeAdaptiveExpiry
updateRuntimeAdaptiveExpiry( $ttl)
Lower the runtime adaptive TTL to at most this value.
Definition: ParserOutput.php:1758
ParserOutput\getTimeSinceStart
getTimeSinceStart( $clock)
Returns the time since resetParseStartTime() was last called.
Definition: ParserOutput.php:1552
$modules
$modules
Definition: HTMLFormElement.php:15
ParserOutput\addImage
addImage( $name, $timestamp=null, $sha1=null)
Register a file dependency for this output.
Definition: ParserOutput.php:1021
ParserOutput\$mHideNewSection
bool $mHideNewSection
Hide the new section link?
Definition: ParserOutput.php:132
ParserOutput\$mTemplates
array $mTemplates
2-D map of NS/DBK to ID for the template references.
Definition: ParserOutput.php:95
ParserOutput\$mNewSection
bool $mNewSection
Show a new section link?
Definition: ParserOutput.php:127
ParserOutput\__wakeup
__wakeup()
Definition: ParserOutput.php:2220
Linker\expandLocalLinks
static expandLocalLinks(string $html)
Helper function to expand local links.
Definition: Linker.php:1376
$args
if( $line===false) $args
Definition: mcc.php:124
ParserOutput\preventClickjacking
preventClickjacking( $flag)
Get or set the prevent-clickjacking flag.
Definition: ParserOutput.php:1743
ParserOutput\addWarningMsg
addWarningMsg(string $msg,... $args)
Add a warning to the output for this page.
Definition: ParserOutput.php:902
ParserOutput\getTimes
static getTimes( $clock=null)
Definition: ParserOutput.php:1520
ParserOutput\addCategory
addCategory( $c, $sort)
Add a category.
Definition: ParserOutput.php:851
ParserOutput\useMaxValue
static useMaxValue( $a, $b)
Definition: ParserOutput.php:2036
ParserOutput\SUPPORTS_STATELESS_TRANSFORMS
const SUPPORTS_STATELESS_TRANSFORMS
Feature flags to indicate to extensions that MediaWiki core supports and uses getText() stateless tra...
Definition: ParserOutput.php:45
ParserOutput\addModuleStyles
addModuleStyles( $modules)
Definition: ParserOutput.php:1092
ParserOutput\mergeInternalMetaDataFrom
mergeInternalMetaDataFrom(ParserOutput $source)
Merges internal metadata such as flags, accessed options, and profiling info from $source into this P...
Definition: ParserOutput.php:1843
ParserOutput\setText
setText( $text)
Definition: ParserOutput.php:810
ParserOutput\$mModuleStyles
array $mModuleStyles
Modules of which only the CSSS will be loaded by ResourceLoader.
Definition: ParserOutput.php:152
ParserOutput\getDisplayTitle
getDisplayTitle()
Get the title to be used for display.
Definition: ParserOutput.php:1177
ParserOutput\$mFlags
array $mFlags
Generic flags.
Definition: ParserOutput.php:244
ParserOutput\getIndicators
getIndicators()
Definition: ParserOutput.php:673
ParserOutput\setLanguageLinks
setLanguageLinks( $ll)
Definition: ParserOutput.php:814
ParserOutput\getSpeculativePageIdUsed
getSpeculativePageIdUsed()
Definition: ParserOutput.php:589
ParserOutput\getPageProperty
getPageProperty(string $name)
Look up a page property.
Definition: ParserOutput.php:1334
ParserOutput\setCategories
setCategories(array $c)
Overwrite the category map.
Definition: ParserOutput.php:860
OutputPage
This is one of the Core classes and should be read at least once by any new developers.
Definition: OutputPage.php:50
ParserOutput\getLanguageLinks
& getLanguageLinks()
Definition: ParserOutput.php:636
ParserOutput\$mPreventClickjacking
bool $mPreventClickjacking
Whether to emit X-Frame-Options: DENY.
Definition: ParserOutput.php:224
ParserOutput\getLinksSpecial
& getLinksSpecial()
Definition: ParserOutput.php:696
ParserOutput\getPageProperties
getPageProperties()
Return all the page properties set on this ParserOutput.
Definition: ParserOutput.php:1352
ParserOutput\newFromJsonArray
static newFromJsonArray(JsonUnserializer $unserializer, array $json)
Creates a new instance of the class and initialized it from the $json array.
Definition: ParserOutput.php:2115
ParserOutput\getExternalLinks
& getExternalLinks()
Definition: ParserOutput.php:716
ParserOutput\getTemplateIds
& getTemplateIds()
Definition: ParserOutput.php:704
OutputPage\getPreventClickjacking
getPreventClickjacking()
Get the prevent-clickjacking flag.
Definition: OutputPage.php:2439
ParserOutput\getTOCHTML
getTOCHTML()
Definition: ParserOutput.php:760
ParserOutput\addOutputHook
addOutputHook( $hook, $data=false)
Definition: ParserOutput.php:910
ParserOutput\getExtraCSPScriptSrcs
getExtraCSPScriptSrcs()
Get extra Content-Security-Policy 'script-src' directives.
Definition: ParserOutput.php:797
ParserOutput\SLOW_AR_TTL
const SLOW_AR_TTL
Definition: ParserOutput.php:280
ParserOutput\getTitleText
getTitleText()
Definition: ParserOutput.php:677
ParserOutput\setPageProperty
setPageProperty(string $name, $value)
Set a page property to be stored in the page_props database table.
Definition: ParserOutput.php:1321
ParserOutput\clearWrapperDivClass
clearWrapperDivClass()
Clears the CSS class to use for the wrapping div, effectively disabling the wrapper div until addWrap...
Definition: ParserOutput.php:546
ParserOutput\setProperty
setProperty( $name, $value)
Sets a page property to be stored in the page_props database table.
Definition: ParserOutput.php:1218
ParserOutput\getNewSection
getNewSection()
Definition: ParserOutput.php:938
$content
$content
Definition: router.php:76
ParserOutput\setExtensionData
setExtensionData( $key, $value)
Attaches arbitrary data to this ParserObject.
Definition: ParserOutput.php:1497
ParserOutput\$mExtensionData
array $mExtensionData
extra data used by extensions.
Definition: ParserOutput.php:203
$s
foreach( $mmfl['setupFiles'] as $fileName) if( $queue) if(empty( $mmfl['quiet'])) $s
Definition: mergeMessageFileList.php:206
NS_MEDIA
const NS_MEDIA
Definition: Defines.php:52
OutputPage\getHeadItemsArray
getHeadItemsArray()
Get an array of head items.
Definition: OutputPage.php:660
ParserOutput\getOutputHooks
getOutputHooks()
Definition: ParserOutput.php:748
ParserOutput\detectAndDecodeBinary
static detectAndDecodeBinary(array $properties)
Finds any associative arrays that represent encoded binary strings, and replaces them with the decode...
Definition: ParserOutput.php:2208
ParserOutput\$speculativePageIdUsed
int null $speculativePageIdUsed
Assumed page ID for {{PAGEID}} if no revision is set.
Definition: ParserOutput.php:256
ParserOutput\getHideNewSection
getHideNewSection()
Definition: ParserOutput.php:934
Parser\replaceTableOfContentsMarker
static replaceTableOfContentsMarker( $text, $toc)
Replace table of contents marker in parsed HTML.
Definition: Parser.php:4770
Hooks\runner
static runner()
Get a HookRunner instance for calling hooks using the new interfaces.
Definition: Hooks.php:173
ParserOutput\detectAndEncodeBinary
static detectAndEncodeBinary(array $properties)
Finds any non-utf8 strings in the given array and replaces them with an associative array that wraps ...
Definition: ParserOutput.php:2184
MediaWiki\Linker\LinkTarget\getDBkey
getDBkey()
Get the main part with underscores.
ParserOutput\$revisionUsedSha1Base36
string null $revisionUsedSha1Base36
SHA-1 base 36 hash of any self-transclusion.
Definition: ParserOutput.php:261
ParserOutput\$mExtraStyleSrcs
array $mExtraStyleSrcs
Extra style-src for CSP.
Definition: ParserOutput.php:239
ParserOutput\getRevisionUsedSha1Base36
getRevisionUsedSha1Base36()
Definition: ParserOutput.php:632
ParserOutput\$mExtraScriptSrcs
array $mExtraScriptSrcs
Extra script-src for CSP.
Definition: ParserOutput.php:229
ParserOutput\$mCategories
array< string, string > $mCategories
Map of category names to sort keys.
Definition: ParserOutput.php:66
ParserOutput\getNoGallery
getNoGallery()
Definition: ParserOutput.php:724
ParserOutput\$mCacheMessage
string $mCacheMessage
Debug message added by ParserCache.
Definition: ParserOutput.php:214
ParserOutput\addWarning
addWarning( $s)
Definition: ParserOutput.php:891
MediaWiki\Json\JsonUnserializer\unserializeArray
unserializeArray(array $array)
Helper to unserialize an array of JsonUnserializable instances or simple types.
RequestContext\getMain
static getMain()
Get the RequestContext object associated with the main request.
Definition: RequestContext.php:484
ParserOutput\$mTemplateIds
array $mTemplateIds
2-D map of NS/DBK to rev ID for the template references.
Definition: ParserOutput.php:101
ParserOutput\getTemplates
& getTemplates()
Definition: ParserOutput.php:700
ParserOutput\setSections
setSections( $toc)
Definition: ParserOutput.php:830
ParserOutput\setCategoryLinks
setCategoryLinks( $cl)
Definition: ParserOutput.php:821
ParserOutput\$mParseStartTime
array $mParseStartTime
Timestamps for getTimeSinceStart().
Definition: ParserOutput.php:219
ParserOutput\getRevisionTimestampUsed
getRevisionTimestampUsed()
Definition: ParserOutput.php:605
ParserOutput\initFromJson
initFromJson(JsonUnserializer $unserializer, array $jsonData)
Initialize member fields from an array returned by jsonSerialize().
Definition: ParserOutput.php:2126
ParserOutput\getFileSearchOptions
& getFileSearchOptions()
Definition: ParserOutput.php:712
ParserOutput\$mTOCHTML
string $mTOCHTML
HTML of the TOC.
Definition: ParserOutput.php:183
ParserOutput\getProperty
getProperty( $name)
Definition: ParserOutput.php:1232
Parser\normalizeLinkUrl
static normalizeLinkUrl( $url)
Replace unusual escape codes in a URL with their equivalent characters.
Definition: Parser.php:2265
ParserOutput\$mExternalLinks
array $mExternalLinks
External link URLs, in the key only.
Definition: ParserOutput.php:116
ParserOutput\$mIndicators
array $mIndicators
Page status indicators, usually displayed in top-right corner.
Definition: ParserOutput.php:71
ParserOutput\FAST_AR_TTL
const FAST_AR_TTL
Definition: ParserOutput.php:279
ParserOutput\addJsConfigVars
addJsConfigVars( $keys, $value=null)
Add one or more variables to be set in mw.config in JavaScript.
Definition: ParserOutput.php:1103
ParserOutput\getCategories
& getCategories()
Definition: ParserOutput.php:665
ParserOutput\hasText
hasText()
Returns true if text was passed to the constructor, or set using setText().
Definition: ParserOutput.php:311
ParserOutput\$mNoGallery
bool $mNoGallery
No gallery on category page? (NOGALLERY).
Definition: ParserOutput.php:137
ParserOutput\getRawText
getRawText()
Get the cacheable text with <mw:editsection> markers still in it.
Definition: ParserOutput.php:323
Html\rawElement
static rawElement( $element, $attribs=[], $contents='')
Returns an HTML element in a string.
Definition: Html.php:213
ParserOutput\useMinValue
static useMinValue( $a, $b)
Definition: ParserOutput.php:2024
ParserOutput\$mIndexPolicy
string $mIndexPolicy
'index' or 'noindex'? Any other value will result in no change.
Definition: ParserOutput.php:198
$keys
$keys
Definition: testCompression.php:72
ParserOutput\getLimitReportData
getLimitReportData()
Definition: ParserOutput.php:771
CacheTime\updateCacheExpiry
updateCacheExpiry( $seconds)
Sets the number of seconds after which this object should expire.
Definition: CacheTime.php:126
$source
$source
Definition: mwdoc-filter.php:34
ParserOutput\useEachMinValue
static useEachMinValue(array $a, array $b)
Definition: ParserOutput.php:2009
ParserOutput\unsetPageProperty
unsetPageProperty(string $name)
Remove a page property.
Definition: ParserOutput.php:1343
ParserOutput\getExtensionData
getExtensionData( $key)
Gets extensions data previously attached to this ParserOutput using setExtensionData().
Definition: ParserOutput.php:1516
ParserOutput\addLanguageLink
addLanguageLink( $t)
Definition: ParserOutput.php:884
ParserOutput\getCategoryNames
getCategoryNames()
Return the names of the categories on this page.
Definition: ParserOutput.php:661
ParserOutput\$mInterwikiLinks
array $mInterwikiLinks
2-D map of prefix/DBK (in keys only) for the inline interwiki links in the document.
Definition: ParserOutput.php:122
ParserOutput\addInterwikiLink
addInterwikiLink( $link)
Definition: ParserOutput.php:1054
Sanitizer\decodeTagAttributes
static decodeTagAttributes( $text)
Return an associative array of attribute names and values from a partial tag string.
Definition: Sanitizer.php:1004
ParserOutput\getText
getText( $options=[])
Get the output HTML.
Definition: ParserOutput.php:363
ParserOutput\setRevisionTimestampUsed
setRevisionTimestampUsed( $timestamp)
Definition: ParserOutput.php:597
$t
$t
Definition: testCompression.php:74
Sanitizer\decodeCharReferences
static decodeCharReferences( $text)
Decode any character references, numeric or named entities, in the text and return a UTF-8 string.
Definition: Sanitizer.php:1228
Html\element
static element( $element, $attribs=[], $contents='')
Identical to rawElement(), but HTML-escapes $contents (like Xml::element()).
Definition: Html.php:235
ParserOutput\$revisionTimestampUsed
int null $revisionTimestampUsed
Assumed rev timestamp for {{REVISIONTIMESTAMP}} if no revision is set.
Definition: ParserOutput.php:258
NS_FILE
const NS_FILE
Definition: Defines.php:70
MediaWiki\Linker\LinkTarget
Definition: LinkTarget.php:26
RawMessage
Variant of the Message class.
Definition: RawMessage.php:35
ParserOutput\$mSections
array $mSections
Table of contents.
Definition: ParserOutput.php:173
ParserOutput\$mText
string null $mText
The output text.
Definition: ParserOutput.php:55
ParserOutput\setTOCHTML
setTOCHTML( $tochtml)
Definition: ParserOutput.php:838
ParserOutput\$mTitleText
string $mTitleText
Title text of the chosen language variant, as HTML.
Definition: ParserOutput.php:76
OutputPage\getJsConfigVars
getJsConfigVars()
Get the javascript config vars to include on this page.
Definition: OutputPage.php:3319
ParserOutput\getSections
getSections()
Definition: ParserOutput.php:684
ParserOutput\$mSpeculativeRevId
int null $mSpeculativeRevId
Assumed rev ID for {{REVISIONID}} if no revision is set.
Definition: ParserOutput.php:246
ParserOutput\hasDynamicContent
hasDynamicContent()
Definition: ParserOutput.php:1709
ParserOutput\addHeadItem
addHeadItem( $section, $tag=false)
Add some text to the "<head>".
Definition: ParserOutput.php:1072
ParserOutput\setEnableOOUI
setEnableOOUI( $enable=false)
Enables OOUI, if true, in any OutputPage instance this ParserOutput object is added to.
Definition: ParserOutput.php:880
ParserOutput\setOutputFlag
setOutputFlag(string $name, bool $val=true)
Provides a uniform interface to various boolean flags stored in the ParserOutput.
Definition: ParserOutput.php:1370
ParserOutput\finalizeAdaptiveCacheExpiry
finalizeAdaptiveCacheExpiry()
Call this when parsing is done to lower the TTL based on low parse times.
Definition: ParserOutput.php:1803
ParserOutput\getSpeculativeRevIdUsed
getSpeculativeRevIdUsed()
Definition: ParserOutput.php:573
ParserOutput\getLinks
& getLinks()
Definition: ParserOutput.php:688
ParserOutput\setIndexPolicy
setIndexPolicy( $policy)
Definition: ParserOutput.php:834
ParserOutput\setNoGallery
setNoGallery( $value)
Definition: ParserOutput.php:720
ParserOutput\getAllFlags
getAllFlags()
Definition: ParserOutput.php:1208
ParserOutput\getIndexPolicy
getIndexPolicy()
Definition: ParserOutput.php:756
ParserOutput\getExtraCSPStyleSrcs
getExtraCSPStyleSrcs()
Get extra Content-Security-Policy 'style-src' directives.
Definition: ParserOutput.php:806
ParserOutput\getWrapperDivClass
getWrapperDivClass()
Returns the class (or classes) to be used with the wrapper div for this otuput.
Definition: ParserOutput.php:557
ParserOutput\getWarnings
getWarnings()
Definition: ParserOutput.php:752
ParserOutput\setHideNewSection
setHideNewSection(bool $value)
Definition: ParserOutput.php:921
ParserOutput\addTemplate
addTemplate( $link, $page_id, $rev_id)
Register a template dependency for this output.
Definition: ParserOutput.php:1035