private $mIndexPolicy = 'index';
private $mFollowPolicy = 'follow';
+
+ /**
+ * @var array Headers that cause the cache to vary. Key is header name, value is an array of
+ * options for the Key header.
+ */
private $mVaryHeader = [
'Accept-Encoding' => [ 'match=gzip' ],
];
* @param array $categories Mapping category name => sort key
*/
public function addCategoryLinks( array $categories ) {
- global $wgContLang;
-
if ( !$categories ) {
return;
}
'OutputPageMakeCategoryLinks',
[ &$outputPage, $categories, &$this->mCategoryLinks ] )
) {
- $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
+ $services = MediaWikiServices::getInstance();
+ $linkRenderer = $services->getLinkRenderer();
foreach ( $categories as $category => $type ) {
// array keys will cast numeric category names to ints, so cast back to string
$category = (string)$category;
if ( !$title ) {
continue;
}
- $wgContLang->findVariantLink( $category, $title, true );
+ $services->getContentLanguage()->findVariantLink( $category, $title, true );
if ( $category != $origcategory && array_key_exists( $category, $categories ) ) {
continue;
}
- $text = $wgContLang->convertHtml( $title->getText() );
+ $text = $services->getContentLanguage()->convertHtml( $title->getText() );
$this->mCategories[$type][] = $title->getText();
$this->mCategoryLinks[$type][] = $linkRenderer->makeLink( $title, new HtmlArmor( $text ) );
}
* @since 1.24
* @param ParserOutput $parserOutput
*/
- public function addParserOutputMetadata( $parserOutput ) {
+ public function addParserOutputMetadata( ParserOutput $parserOutput ) {
$this->mLanguageLinks =
array_merge( $this->mLanguageLinks, $parserOutput->getLanguageLinks() );
$this->addCategoryLinks( $parserOutput->getCategories() );
foreach ( $parserOutput->getOutputHooks() as $hookInfo ) {
list( $hookName, $data ) = $hookInfo;
if ( isset( $parserOutputHooks[$hookName] ) ) {
- call_user_func( $parserOutputHooks[$hookName], $this, $parserOutput, $data );
+ $parserOutputHooks[$hookName]( $this, $parserOutput, $data );
}
}
* @param ParserOutput $parserOutput
* @param array $poOptions Options to ParserOutput::getText()
*/
- public function addParserOutputContent( $parserOutput, $poOptions = [] ) {
+ public function addParserOutputContent( ParserOutput $parserOutput, $poOptions = [] ) {
$this->addParserOutputText( $parserOutput, $poOptions );
$this->addModules( $parserOutput->getModules() );
* @param ParserOutput $parserOutput
* @param array $poOptions Options to ParserOutput::getText()
*/
- public function addParserOutputText( $parserOutput, $poOptions = [] ) {
+ public function addParserOutputText( ParserOutput $parserOutput, $poOptions = [] ) {
$text = $parserOutput->getText( $poOptions );
// Avoid PHP 7.1 warning of passing $this by reference
$outputPage = $this;
* @param ParserOutput $parserOutput
* @param array $poOptions Options to ParserOutput::getText()
*/
- function addParserOutput( $parserOutput, $poOptions = [] ) {
+ function addParserOutput( ParserOutput $parserOutput, $poOptions = [] ) {
$this->addParserOutputMetadata( $parserOutput );
$this->addParserOutputText( $parserOutput, $poOptions );
}
*
* @param string $text
* @param bool $linestart Is this the start of a line?
- * @param bool $interface Use interface language ($wgLang instead of
- * $wgContLang) while parsing language sensitive magic words like GRAMMAR and PLURAL.
- * This also disables LanguageConverter.
+ * @param bool $interface Use interface language (instead of content language) while parsing
+ * language sensitive magic words like GRAMMAR and PLURAL. This also disables
+ * LanguageConverter.
* @param Language|null $language Target language object, will override $interface
* @throws MWException
* @return string HTML
*
* @param string $text
* @param bool $linestart Is this the start of a line?
- * @param bool $interface Use interface language ($wgLang instead of
- * $wgContLang) while parsing language sensitive magic
- * words like GRAMMAR and PLURAL
+ * @param bool $interface Use interface language (instead of content language) while parsing
+ * language sensitive magic words like GRAMMAR and PLURAL
* @return string HTML
*/
public function parseInline( $text, $linestart = true, $interface = false ) {
}
/**
- * Lower the value of the "s-maxage" part of the "Cache-control" HTTP header
+ * Set the value of the "s-maxage" part of the "Cache-control" HTTP header to $maxage if that is
+ * lower than the current s-maxage. Either way, $maxage is now an upper limit on s-maxage, so
+ * that future calls to setCdnMaxage() will no longer be able to raise the s-maxage above
+ * $maxage.
*
* @param int $maxage Maximum cache time on the CDN, in seconds
* @since 1.27
* TTL is 90% of the age of the object, subject to the min and max.
*
* @param string|int|float|bool|null $mtime Last-Modified timestamp
- * @param int $minTTL Mimimum TTL in seconds [default: 1 minute]
+ * @param int $minTTL Minimum TTL in seconds [default: 1 minute]
* @param int $maxTTL Maximum TTL in seconds [default: $wgSquidMaxage]
- * @return int TTL in seconds
+ * @return int TTL in seconds passed to lowerCdnMaxage() (may not be the same as the new
+ * s-maxage)
* @since 1.28
*/
public function adaptCdnTTL( $mtime, $minTTL = 0, $maxTTL = 0 ) {
/**
* Use enableClientCache(false) to force it to send nocache headers
*
- * @param bool $state
+ * @param bool|null $state New value, or null to not set the value
*
- * @return bool
+ * @return bool Old value
*/
public function enableClientCache( $state ) {
return wfSetVar( $this->mEnableClientCache, $state );
}
/**
- * Get the list of cookies that will influence on the cache
+ * Get the list of cookie names that will influence the cache
*
* @return array
*/
if ( !is_array( $option ) ) {
$option = [];
}
- $this->mVaryHeader[$header] = array_unique( array_merge( $this->mVaryHeader[$header], $option ) );
+ $this->mVaryHeader[$header] =
+ array_unique( array_merge( $this->mVaryHeader[$header], $option ) );
}
/**
}
/**
- * T23672: Add Accept-Language to Vary and Key headers
- * if there's no 'variant' parameter existed in GET.
+ * T23672: Add Accept-Language to Vary and Key headers if there's no 'variant' parameter in GET.
*
* For example:
- * /w/index.php?title=Main_page should always be served; but
- * /w/index.php?title=Main_page&variant=zh-cn should never be served.
+ * /w/index.php?title=Main_page will vary based on Accept-Language; but
+ * /w/index.php?title=Main_page&variant=zh-cn will not.
*/
- function addAcceptLanguage() {
+ private function addAcceptLanguage() {
$title = $this->getTitle();
if ( !$title instanceof Title ) {
return;
foreach ( $variants as $variant ) {
if ( $variant === $lang->getCode() ) {
continue;
- } else {
- $aloption[] = 'substr=' . $variant;
-
- // IE and some other browsers use BCP 47 standards in
- // their Accept-Language header, like "zh-CN" or "zh-Hant".
- // We should handle these too.
- $variantBCP47 = LanguageCode::bcp47( $variant );
- if ( $variantBCP47 !== $variant ) {
- $aloption[] = 'substr=' . $variantBCP47;
- }
+ }
+
+ $aloption[] = "substr=$variant";
+
+ // IE and some other browsers use BCP 47 standards in their Accept-Language header,
+ // like "zh-CN" or "zh-Hant". We should handle these too.
+ $variantBCP47 = LanguageCode::bcp47( $variant );
+ if ( $variantBCP47 !== $variant ) {
+ $aloption[] = "substr=$variantBCP47";
}
}
$this->addVaryHeader( 'Accept-Language', $aloption );
* @throws MWException
*/
public function output( $return = false ) {
- global $wgContLang;
-
if ( $this->mDoNothing ) {
return $return ? '' : null;
}
ob_start();
$response->header( 'Content-type: ' . $config->get( 'MimeType' ) . '; charset=UTF-8' );
- $response->header( 'Content-language: ' . $wgContLang->getHtmlCode() );
+ $response->header( 'Content-language: ' .
+ MediaWikiServices::getInstance()->getContentLanguage()->getHtmlCode() );
if ( !$this->mArticleBodyOnly ) {
$sk = $this->getSkin();
-
- if ( $sk->shouldPreloadLogo() ) {
- $this->addLogoPreloadLinkHeaders();
- }
}
$linkHeader = $this->getLinkHeader();
$this->rlClientContext = new DerivativeResourceLoaderContext( $this->rlClientContext );
$this->rlClientContext->setContentOverrideCallback( function ( Title $title ) {
foreach ( $this->contentOverrideCallbacks as $callback ) {
- $content = call_user_func( $callback, $title );
+ $content = $callback( $title );
if ( $content !== null ) {
return $content;
}
* @return string The doctype, opening "<html>", and head element.
*/
public function headElement( Skin $sk, $includeStyle = true ) {
- global $wgContLang;
-
$userdir = $this->getLanguage()->getDir();
- $sitedir = $wgContLang->getDir();
+ $sitedir = MediaWikiServices::getInstance()->getContentLanguage()->getDir();
$pieces = [];
$pieces[] = Html::htmlHeader( Sanitizer::mergeAttributes(
* @return array
*/
public function getJSVars() {
- global $wgContLang;
-
$curRevisionId = 0;
$articleId = 0;
$canonicalSpecialPageName = false; # T23115
+ $services = MediaWikiServices::getInstance();
$title = $this->getTitle();
$ns = $title->getNamespace();
if ( $ns == NS_SPECIAL ) {
list( $canonicalSpecialPageName, /*...*/ ) =
- SpecialPageFactory::resolveAlias( $title->getDBkey() );
+ $services->getSpecialPageFactory()->
+ resolveAlias( $title->getDBkey() );
} elseif ( $this->canUseWikiPage() ) {
$wikiPage = $this->getWikiPage();
$curRevisionId = $wikiPage->getLatest();
$vars['wgUserNewMsgRevisionId'] = $user->getNewMessageRevisionId();
}
- if ( $wgContLang->hasVariants() ) {
- $vars['wgUserVariant'] = $wgContLang->getPreferredVariant();
+ $contLang = $services->getContentLanguage();
+ if ( $contLang->hasVariants() ) {
+ $vars['wgUserVariant'] = $contLang->getPreferredVariant();
}
// Same test as SkinTemplate
$vars['wgIsProbablyEditable'] = $title->quickUserCan( 'edit', $user )
] );
}
- /**
- * Add Link headers for preloading the wiki's logo.
- *
- * @since 1.26
- */
- protected function addLogoPreloadLinkHeaders() {
- $logo = ResourceLoaderSkinModule::getLogo( $this->getConfig() );
-
- $tags = [];
- $logosPerDppx = [];
- $logos = [];
-
- if ( !is_array( $logo ) ) {
- // No media queries required if we only have one variant
- $this->addLinkHeader( '<' . $logo . '>;rel=preload;as=image' );
- return;
- }
-
- if ( isset( $logo['svg'] ) ) {
- // No media queries required if we only have a 1x and svg variant
- // because all preload-capable browsers support SVGs
- $this->addLinkHeader( '<' . $logo['svg'] . '>;rel=preload;as=image' );
- return;
- }
-
- foreach ( $logo as $dppx => $src ) {
- // Keys are in this format: "1.5x"
- $dppx = substr( $dppx, 0, -1 );
- $logosPerDppx[$dppx] = $src;
- }
-
- // Because PHP can't have floats as array keys
- uksort( $logosPerDppx, function ( $a , $b ) {
- $a = floatval( $a );
- $b = floatval( $b );
- // Sort from smallest to largest (e.g. 1x, 1.5x, 2x)
- return $a <=> $b;
- } );
-
- foreach ( $logosPerDppx as $dppx => $src ) {
- $logos[] = [ 'dppx' => $dppx, 'src' => $src ];
- }
-
- $logosCount = count( $logos );
- // Logic must match ResourceLoaderSkinModule:
- // - 1x applies to resolution < 1.5dppx
- // - 1.5x applies to resolution >= 1.5dppx && < 2dppx
- // - 2x applies to resolution >= 2dppx
- // Note that min-resolution and max-resolution are both inclusive.
- for ( $i = 0; $i < $logosCount; $i++ ) {
- if ( $i === 0 ) {
- // Smallest dppx
- // min-resolution is ">=" (larger than or equal to)
- // "not min-resolution" is essentially "<"
- $media_query = 'not all and (min-resolution: ' . $logos[ 1 ]['dppx'] . 'dppx)';
- } elseif ( $i !== $logosCount - 1 ) {
- // In between
- // Media query expressions can only apply "not" to the entire expression
- // (e.g. can't express ">= 1.5 and not >= 2).
- // Workaround: Use <= 1.9999 in place of < 2.
- $upper_bound = floatval( $logos[ $i + 1 ]['dppx'] ) - 0.000001;
- $media_query = '(min-resolution: ' . $logos[ $i ]['dppx'] .
- 'dppx) and (max-resolution: ' . $upper_bound . 'dppx)';
- } else {
- // Largest dppx
- $media_query = '(min-resolution: ' . $logos[ $i ]['dppx'] . 'dppx)';
- }
-
- $this->addLinkHeader(
- '<' . $logos[$i]['src'] . '>;rel=preload;as=image;media=' . $media_query
- );
- }
- }
-
/**
* Get (and set if not yet set) the CSP nonce.
*