*/
public $mBodytext = '';
- /**
- * Holds the debug lines that will be output as comments in page source if
- * $wgDebugComments is enabled. See also $wgShowDebug.
- * @deprecated since 1.20; use MWDebug class instead.
- */
- public $mDebugtext = '';
-
/** @var string Stores contents of "<title>" tag */
private $mHTMLtitle = '';
$lb->setArray( $arr );
# Fetch existence plus the hiddencat property
- $dbr = wfGetDB( DB_SLAVE );
+ $dbr = wfGetDB( DB_REPLICA );
$fields = array_merge(
LinkCache::getSelectFields(),
[ 'page_namespace', 'page_title', 'pp_value' ]
}
// Include profiling data
- $this->setLimitReportData( $parserOutput->getLimitReportData() );
+ if ( !$this->limitReportData ) {
+ $this->setLimitReportData( $parserOutput->getLimitReportData() );
+ }
// Link flags are ignored for now, but may in the future be
// used to mark individual language links.
$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
*
/**
* Finally, all the text has been munged and accumulated into
* the object, let's actually output it:
+ *
+ * @param bool $return Set to true to get the result as a string rather than sending it
+ * @return string|null
+ * @throws Exception
+ * @throws FatalError
+ * @throws MWException
*/
- public function output() {
+ public function output( $return = false ) {
+ global $wgContLang;
+
if ( $this->mDoNothing ) {
- return;
+ return $return ? '' : null;
}
$response = $this->getRequest()->response();
}
}
- return;
+ return $return ? '' : null;
} elseif ( $this->mStatusCode ) {
$response->statusHeader( $this->mStatusCode );
}
ob_start();
$response->header( 'Content-type: ' . $config->get( 'MimeType' ) . '; charset=UTF-8' );
- $response->header( 'Content-language: ' . $config->get( 'LanguageCode' ) );
+ $response->header( 'Content-language: ' . $wgContLang->getHtmlCode() );
// Avoid Internet Explorer "compatibility view" in IE 8-10, so that
// jQuery etc. can work correctly.
$this->sendCacheControl();
- ob_end_flush();
-
+ if ( $return ) {
+ return ob_get_clean();
+ } else {
+ ob_end_flush();
+ return null;
+ }
}
/**
* Output a standard error page
*
* showErrorPage( 'titlemsg', 'pagetextmsg' );
- * showErrorPage( 'titlemsg', 'pagetextmsg', array( 'param1', 'param2' ) );
+ * showErrorPage( 'titlemsg', 'pagetextmsg', [ 'param1', 'param2' ] );
* showErrorPage( 'titlemsg', $messageObject );
* showErrorPage( $titleMessageObject, $messageObject );
*
/**
* 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
}
/**
- * Show a warning about slave lag
+ * Show a warning about replica DB lag
*
* If the lag is higher than $wgSlaveLagCritical seconds,
* then the warning is a bit more obvious. If the lag is
// Prepare exempt modules for buildExemptModules()
$exemptGroups = [ 'site' => [], 'noscript' => [], 'private' => [], 'user' => [] ];
$exemptStates = [];
- $moduleStyles = array_filter( $this->getModuleStyles( /*filter*/ true ),
+ $moduleStyles = $this->getModuleStyles( /*filter*/ true );
+
+ // 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,
function ( $name ) use ( $rl, $context, &$exemptGroups, &$exemptStates ) {
$module = $rl->getModule( $name );
if ( $module ) {
- $group = $module->getGroup();
if ( $name === 'user.styles' && $this->isUserCssPreview() ) {
$exemptStates[$name] = 'ready';
// Special case in buildExemptModules()
return false;
}
+ $group = $module->getGroup();
if ( isset( $exemptGroups[$group] ) ) {
$exemptStates[$name] = 'ready';
if ( !$module->isKnownEmpty( $context ) ) {
);
$this->rlExemptStyleModules = $exemptGroups;
- // Manually handled by getBottomScripts()
- $userModule = $rl->getModule( 'user' );
- $userState = $userModule->isKnownEmpty( $context ) && !$this->isUserJsPreview()
- ? 'ready'
- : 'loading';
- $this->rlUserModuleState = $exemptStates['user'] = $userState;
+ $isUserModuleFiltered = !$this->filterModules( [ 'user' ] );
+ // If this page filters out 'user', makeResourceLoaderLink will drop it.
+ // Avoid indefinite "loading" state or untrue "ready" state (T145368).
+ if ( !$isUserModuleFiltered ) {
+ // Manually handled by getBottomScripts()
+ $userModule = $rl->getModule( 'user' );
+ $userState = $userModule->isKnownEmpty( $context ) && !$this->isUserJsPreview()
+ ? 'ready'
+ : 'loading';
+ $this->rlUserModuleState = $exemptStates['user'] = $userState;
+ }
$rlClient = new ResourceLoaderClientHtml( $context, $this->getTarget() );
$rlClient->setConfig( $this->getJSVars() );
}
}
- $chunks[] = ResourceLoader::makeInlineScript(
- ResourceLoader::makeConfigSetScript(
- [ 'wgPageParseReport' => $this->limitReportData ],
- true
- )
- );
+ if ( $this->limitReportData ) {
+ $chunks[] = ResourceLoader::makeInlineScript(
+ ResourceLoader::makeConfigSetScript(
+ [ 'wgPageParseReport' => $this->limitReportData ],
+ true
+ )
+ );
+ }
return self::combineWrappedStrings( $chunks );
}
if ( $user->isLoggedIn() ) {
$vars['wgUserId'] = $user->getId();
$vars['wgUserEditCount'] = $user->getEditCount();
- $userReg = wfTimestampOrNull( TS_UNIX, $user->getRegistration() );
- $vars['wgUserRegistration'] = $userReg !== null ? ( $userReg * 1000 ) : null;
+ $userReg = $user->getRegistration();
+ $vars['wgUserRegistration'] = $userReg ? wfTimestamp( TS_UNIX, $userReg ) * 1000 : null;
// Get the revision ID of the oldest new message on the user's talk
// page. This can be used for constructing new message alerts on
// the client side.