*/
private $copyrightUrl;
- /** @var array Profiling data */
- private $limitReportData = [];
-
/**
* Constructor for OutputPage. This should not be called directly.
* Instead a new RequestContext should be created and it will implicitly create
/**
* Add new language links
*
- * @param array $newLinkArray Associative array mapping language code to the page
- * name
+ * @param string[] $newLinkArray Array of interwiki-prefixed (non DB key) titles
+ * (e.g. 'fr:Test page')
*/
public function addLanguageLinks( array $newLinkArray ) {
$this->mLanguageLinks += $newLinkArray;
/**
* Reset the language links and add new language links
*
- * @param array $newLinkArray Associative array mapping language code to the page
- * name
+ * @param string[] $newLinkArray Array of interwiki-prefixed (non DB key) titles
+ * (e.g. 'fr:Test page')
*/
public function setLanguageLinks( array $newLinkArray ) {
$this->mLanguageLinks = $newLinkArray;
/**
* Get the list of language links
*
- * @return array Array of Interwiki Prefixed (non DB key) Titles (e.g. 'fr:Test page')
+ * @return string[] Array of interwiki-prefixed (non DB key) titles (e.g. 'fr:Test page')
*/
public function getLanguageLinks() {
return $this->mLanguageLinks;
$popts->setTidy( $oldTidy );
$this->addParserOutput( $parserOutput );
-
}
/**
}
}
- // Enable OOUI if requested via ParserOutput
+ // enable OOUI if requested via ParserOutput
if ( $parserOutput->getEnableOOUI() ) {
$this->enableOOUI();
}
- // Include profiling data
- $this->setLimitReportData( $parserOutput->getLimitReportData() );
-
// Link flags are ignored for now, but may in the future be
// used to mark individual language links.
$linkFlags = [];
$this->setCdnMaxage( $this->mCdnMaxage );
}
+ /**
+ * Get TTL in [$minTTL,$maxTTL] in pass it to lowerCdnMaxage()
+ *
+ * This sets and returns $minTTL if $mtime is false or null. Otherwise,
+ * the TTL is higher the older the $mtime timestamp is. Essentially, the
+ * TTL is 90% of the age of the object, subject to the min and max.
+ *
+ * @param string|integer|float|bool|null $mtime Last-Modified timestamp
+ * @param integer $minTTL Mimimum TTL in seconds [default: 1 minute]
+ * @param integer $maxTTL Maximum TTL in seconds [default: $wgSquidMaxage]
+ * @return integer TTL in seconds
+ * @since 1.28
+ */
+ public function adaptCdnTTL( $mtime, $minTTL = 0, $maxTTL = 0 ) {
+ $minTTL = $minTTL ?: IExpiringStore::TTL_MINUTE;
+ $maxTTL = $maxTTL ?: $this->getConfig()->get( 'SquidMaxage' );
+
+ if ( $mtime === null || $mtime === false ) {
+ return $minTTL; // entity does not exist
+ }
+
+ $age = time() - wfTimestamp( TS_UNIX, $mtime );
+ $adaptiveTTL = max( .9 * $age, $minTTL );
+ $adaptiveTTL = min( $adaptiveTTL, $maxTTL );
+
+ $this->lowerCdnMaxage( (int)$adaptiveTTL );
+
+ return $adaptiveTTL;
+ }
+
/**
* Use enableClientCache(false) to force it to send nocache headers
*
# We'll purge the proxy cache explicitly, but require end user agents
# to revalidate against the proxy on each visit.
# Surrogate-Control controls our CDN, Cache-Control downstream caches
- wfDebug( __METHOD__ . ": proxy caching with ESI; {$this->mLastModified} **", 'private' );
+ wfDebug( __METHOD__ .
+ ": proxy caching with ESI; {$this->mLastModified} **", 'private' );
# start with a shorter timeout for initial testing
# header( 'Surrogate-Control: max-age=2678400+2678400, content="ESI/1.0"');
- $response->header( 'Surrogate-Control: max-age=' . $config->get( 'SquidMaxage' )
- . '+' . $this->mCdnMaxage . ', content="ESI/1.0"' );
+ $response->header(
+ "Surrogate-Control: max-age={$config->get( 'SquidMaxage' )}" .
+ "+{$this->mCdnMaxage}, content=\"ESI/1.0\""
+ );
$response->header( 'Cache-Control: s-maxage=0, must-revalidate, max-age=0' );
} else {
# We'll purge the proxy cache for anons explicitly, but require end user agents
# to revalidate against the proxy on each visit.
# IMPORTANT! The CDN needs to replace the Cache-Control header with
# Cache-Control: s-maxage=0, must-revalidate, max-age=0
- wfDebug( __METHOD__ . ": local proxy caching; {$this->mLastModified} **", 'private' );
+ wfDebug( __METHOD__ .
+ ": local proxy caching; {$this->mLastModified} **", 'private' );
# start with a shorter timeout for initial testing
# header( "Cache-Control: s-maxage=2678400, must-revalidate, max-age=0" );
- $response->header( 'Cache-Control: s-maxage=' . $this->mCdnMaxage
- . ', must-revalidate, max-age=0' );
+ $response->header( "Cache-Control: " .
+ "s-maxage={$this->mCdnMaxage}, must-revalidate, max-age=0" );
}
} else {
# We do want clients to cache if they can, but they *must* check for updates
/**
* Output a standard permission error page
*
- * @param array $errors Error message keys
+ * @param array $errors Error message keys or [key, param...] arrays
* @param string $action Action that was denied or null if unknown
*/
public function showPermissionsErrorPage( array $errors, $action = null ) {
+ foreach ( $errors as $key => $error ) {
+ $errors[$key] = (array)$error;
+ }
+
// For some action (read, edit, create and upload), display a "login to do this action"
// error if all of the following conditions are met:
// 1. the user is not logged in
$exemptStates = [];
$moduleStyles = $this->getModuleStyles( /*filter*/ true );
- // Batch preload getTitleInfo for isKnownEmpty() calls below
- $exemptModules = array_filter( $moduleStyles,
- function ( $name ) use ( $rl, &$exemptGroups ) {
- $module = $rl->getModule( $name );
- return $module && isset( $exemptGroups[ $module->getGroup() ] );
- }
- );
- ResourceLoaderWikiModule::preloadTitleInfo(
- $context, wfGetDB( DB_REPLICA ), $exemptModules );
+ // Preload getTitleInfo for isKnownEmpty calls below and in ResourceLoaderClientHtml
+ // Separate user-specific batch for improved cache-hit ratio.
+ $userBatch = [ 'user.styles', 'user' ];
+ $siteBatch = array_diff( $moduleStyles, $userBatch );
+ $dbr = wfGetDB( DB_REPLICA );
+ ResourceLoaderWikiModule::preloadTitleInfo( $context, $dbr, $siteBatch );
+ ResourceLoaderWikiModule::preloadTitleInfo( $context, $dbr, $userBatch );
// Filter out modules handled by buildExemptModules()
$moduleStyles = array_filter( $moduleStyles,
// The spec recommends defining XHTML5's charset using the XML declaration
// instead of meta.
// Our XML declaration is output by Html::htmlHeader.
- // http://www.whatwg.org/html/semantics.html#attr-meta-http-equiv-content-type
- // http://www.whatwg.org/html/semantics.html#charset
+ // https://html.spec.whatwg.org/multipage/semantics.html#attr-meta-http-equiv-content-type
+ // https://html.spec.whatwg.org/multipage/semantics.html#charset
$pieces[] = Html::element( 'meta', [ 'charset' => 'UTF-8' ] );
}
}
}
- $chunks[] = ResourceLoader::makeInlineScript(
- ResourceLoader::makeConfigSetScript(
- [ 'wgPageParseReport' => $this->limitReportData ],
- true
- )
- );
-
return self::combineWrappedStrings( $chunks );
}
public static function transformCssMedia( $media ) {
global $wgRequest;
- // http://www.w3.org/TR/css3-mediaqueries/#syntax
+ // https://www.w3.org/TR/css3-mediaqueries/#syntax
$screenMediaQueryRegex = '/^(?:only\s+)?screen\b/i';
// Switch in on-screen display for media testing
'mediawiki.widgets.styles',
] );
}
-
- /**
- * @param array $data Data from ParserOutput::getLimitReportData()
- * @since 1.28
- */
- public function setLimitReportData( array $data ) {
- $this->limitReportData = $data;
- }
}