Map of category names to sort keys
*/
private $mCategories;
/**
* @var array Page status indicators, usually displayed in top-right corner.
*/
private $mIndicators = [];
/**
* @var string Title text of the chosen language variant, as HTML.
*/
private $mTitleText;
/**
* @var int[][] 2-D map of NS/DBK to ID for the links in the document.
* ID=zero for broken.
* @phan-var array>
*/
private $mLinks = [];
/**
* @var array Keys are DBKs for the links to special pages in the document.
* @since 1.35
*/
private $mLinksSpecial = [];
/**
* @var array 2-D map of NS/DBK to ID for the template references.
* ID=zero for broken.
*/
private $mTemplates = [];
/**
* @var array 2-D map of NS/DBK to rev ID for the template references.
* ID=zero for broken.
*/
private $mTemplateIds = [];
/**
* @var array DB keys of the images used, in the array key only
*/
private $mImages = [];
/**
* @var array DB keys of the images used mapped to sha1 and MW timestamp.
*/
private $mFileSearchOptions = [];
/**
* @var array External link URLs, in the key only.
*/
private $mExternalLinks = [];
/**
* @var array 2-D map of prefix/DBK (in keys only)
* for the inline interwiki links in the document.
*/
private $mInterwikiLinks = [];
/**
* @var bool Show a new section link?
*/
private $mNewSection = false;
/**
* @var bool Hide the new section link?
*/
private $mHideNewSection = false;
/**
* @var bool No gallery on category page? (__NOGALLERY__).
*/
private $mNoGallery = false;
/**
* @var array Items to put in the section
*/
private $mHeadItems = [];
/**
* @var array Modules to be loaded by ResourceLoader
*/
private $mModules = [];
/**
* @var array Modules of which only the CSSS will be loaded by ResourceLoader.
*/
private $mModuleStyles = [];
/**
* @var array JavaScript config variable for mw.config combined with this page.
*/
private $mJsConfigVars = [];
/**
* @var array Hook tags as per $wgParserOutputHooks.
*/
private $mOutputHooks = [];
/**
* @var array Warning text to be returned to the user.
* Wikitext formatted, in the key only.
*/
private $mWarnings = [];
/**
* @var array Table of contents
*/
private $mSections = [];
/**
* @var array Name/value pairs to be cached in the DB.
*/
private $mProperties = [];
/**
* @var string HTML of the TOC.
*/
private $mTOCHTML = '';
/**
* @var string Timestamp of the revision.
*/
private $mTimestamp;
/**
* @var bool Whether OOUI should be enabled.
*/
private $mEnableOOUI = false;
/**
* @var string 'index' or 'noindex'? Any other value will result in no change.
*/
private $mIndexPolicy = '';
/**
* @var array extra data used by extensions.
*/
private $mExtensionData = [];
/**
* @var array Parser limit report data.
*/
private $mLimitReportData = [];
/** @var array Parser limit report data for JSON */
private $mLimitReportJSData = [];
/** @var string Debug message added by ParserCache */
private $mCacheMessage = '';
/**
* @var array Timestamps for getTimeSinceStart().
*/
private $mParseStartTime = [];
/**
* @var bool Whether to emit X-Frame-Options: DENY.
*/
private $mPreventClickjacking = false;
/**
* @var array Extra script-src for CSP
*/
private $mExtraScriptSrcs = [];
/**
* @var array Extra default-src for CSP [Everything but script and style]
*/
private $mExtraDefaultSrcs = [];
/**
* @var array Extra style-src for CSP
*/
private $mExtraStyleSrcs = [];
/**
* @var array Generic flags.
*/
private $mFlags = [];
/** @var string[] */
private const SPECULATIVE_FIELDS = [
'speculativePageIdUsed',
'mSpeculativeRevId',
'revisionTimestampUsed'
];
/** @var int|null Assumed rev ID for {{REVISIONID}} if no revision is set */
private $mSpeculativeRevId;
/** @var int|null Assumed page ID for {{PAGEID}} if no revision is set */
private $speculativePageIdUsed;
/** @var int|null Assumed rev timestamp for {{REVISIONTIMESTAMP}} if no revision is set */
private $revisionTimestampUsed;
/** @var string|null SHA-1 base 36 hash of any self-transclusion */
private $revisionUsedSha1Base36;
/** string CSS classes to use for the wrapping div, stored in the array keys.
* If no class is given, no wrapper is added.
*/
private $mWrapperDivClasses = [];
/** @var int Upper bound of expiry based on parse duration */
private $mMaxAdaptiveExpiry = INF;
private const EDITSECTION_REGEX =
'#<(?:mw:)?editsection page="(.*?)" section="(.*?)"(?:/>|>(.*?)((?:mw:)?editsection>))#s';
// finalizeAdaptiveCacheExpiry() uses TTL = MAX( m * PARSE_TIME + b, MIN_AR_TTL)
// Current values imply that m=3933.333333 and b=-333.333333
// See https://www.nngroup.com/articles/website-response-times/
private const PARSE_FAST_SEC = 0.100; // perceived "fast" page parse
private const PARSE_SLOW_SEC = 1.0; // perceived "slow" page parse
private const FAST_AR_TTL = 60; // adaptive TTL for "fast" pages
private const SLOW_AR_TTL = 3600; // adaptive TTL for "slow" pages
private const MIN_AR_TTL = 15; // min adaptive TTL (for sanity, pool counter, and edit stashing)
/**
* @param string|null $text HTML. Use null to indicate that this ParserOutput contains only
* meta-data, and the HTML output is undetermined, as opposed to empty. Passing null
* here causes hasText() to return false.
* @param array $languageLinks
* @param array $categoryLinks
* @param bool $unused
* @param string $titletext
*/
public function __construct( $text = '', $languageLinks = [], $categoryLinks = [],
$unused = false, $titletext = ''
) {
$this->mText = $text;
$this->mLanguageLinks = $languageLinks;
$this->mCategories = $categoryLinks;
$this->mTitleText = $titletext;
}
/**
* Returns true if text was passed to the constructor, or set using setText(). Returns false
* if null was passed to the $text parameter of the constructor to indicate that this
* ParserOutput only contains meta-data, and the HTML output is undetermined.
*
* @since 1.32
*
* @return bool Whether this ParserOutput contains rendered text. If this returns false, the
* ParserOutput contains meta-data only.
*/
public function hasText() {
return ( $this->mText !== null );
}
/**
* Get the cacheable text with markers still in it. The
* return value is suitable for writing back via setText() but is not valid
* for display to the user.
*
* @return string
* @since 1.27
*/
public function getRawText() {
if ( $this->mText === null ) {
throw new LogicException( 'This ParserOutput contains no text!' );
}
return $this->mText;
}
/**
* Get the output HTML
*
* @param array $options (since 1.31) Transformations to apply to the HTML
* - allowTOC: (bool) Show the TOC, assuming there were enough headings
* to generate one and `__NOTOC__` wasn't used. Default is true,
* but might be statefully overridden.
* - injectTOC: (bool) Replace the TOC_PLACEHOLDER with TOC contents;
* otherwise the marker will be left in the article (and the skin
* will be responsible for replacing or removing it). Default is
* true.
* - enableSectionEditLinks: (bool) Include section edit links, assuming
* section edit link tokens are present in the HTML. Default is true,
* but might be statefully overridden.
* - skin: (Skin) Skin object used for transforming section edit links.
* - unwrap: (bool) Return text without a wrapper div. Default is false,
* meaning a wrapper div will be added if getWrapperDivClass() returns
* a non-empty string.
* - wrapperDivClass: (string) Wrap the output in a div and apply the given
* CSS class to that div. This overrides the output of getWrapperDivClass().
* Setting this to an empty string has the same effect as 'unwrap' => true.
* - deduplicateStyles: (bool) When true, which is the default, `#s',
static function ( $m ) use ( &$seen ) {
$attr = Sanitizer::decodeTagAttributes( $m[1] );
if ( !isset( $attr['data-mw-deduplicate'] ) ) {
return $m[0];
}
$key = $attr['data-mw-deduplicate'];
if ( !isset( $seen[$key] ) ) {
$seen[$key] = true;
return $m[0];
}
// We were going to use an empty