X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;ds=sidebyside;f=includes%2FOutputPage.php;h=76bfaa26f9f366e4a6046f9776723002c9589e28;hb=69ae945e8d39972a07bea89ddb64bc0189b43ac2;hp=48e6cc42b8559d6f5b88a9b17a56a2f0666b6b2e;hpb=4a3e3c95b387c5f1212d6d7dee4b9e5294cfb7a6;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/OutputPage.php b/includes/OutputPage.php index 48e6cc42b8..76bfaa26f9 100644 --- a/includes/OutputPage.php +++ b/includes/OutputPage.php @@ -67,13 +67,6 @@ class OutputPage extends ContextSource { */ 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 "" tag */ private $mHTMLtitle = ''; @@ -1221,8 +1214,8 @@ class OutputPage extends ContextSource { /** * 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; @@ -1231,8 +1224,8 @@ class OutputPage extends ContextSource { /** * 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; @@ -1241,7 +1234,7 @@ class OutputPage extends ContextSource { /** * 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; @@ -1265,7 +1258,7 @@ class OutputPage extends ContextSource { $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' ] @@ -1720,7 +1713,6 @@ class OutputPage extends ContextSource { $popts->setTidy( $oldTidy ); $this->addParserOutput( $parserOutput ); - } /** @@ -1789,7 +1781,9 @@ class OutputPage extends ContextSource { } // 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. @@ -2203,22 +2197,26 @@ class OutputPage extends ContextSource { # 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 @@ -2244,10 +2242,18 @@ class OutputPage extends ContextSource { /** * 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(); @@ -2283,7 +2289,7 @@ class OutputPage extends ContextSource { } } - return; + return $return ? '' : null; } elseif ( $this->mStatusCode ) { $response->statusHeader( $this->mStatusCode ); } @@ -2292,7 +2298,7 @@ class OutputPage extends ContextSource { 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. @@ -2333,7 +2339,6 @@ class OutputPage extends ContextSource { // Hook that allows last minute changes to the output page, e.g. // adding of CSS or Javascript by extensions. Hooks::run( 'BeforePageDisplay', [ &$this, &$sk ] ); - $this->getSkin()->setupSkinUserCss( $this ); try { $sk->outputPage(); @@ -2353,8 +2358,12 @@ class OutputPage extends ContextSource { $this->sendCacheControl(); - ob_end_flush(); - + if ( $return ) { + return ob_get_clean(); + } else { + ob_end_flush(); + return null; + } } /** @@ -2384,7 +2393,7 @@ class OutputPage extends ContextSource { * 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 ); * @@ -2416,10 +2425,14 @@ class OutputPage extends ContextSource { /** * 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 @@ -2566,7 +2579,7 @@ class OutputPage extends ContextSource { } /** - * 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 @@ -2577,6 +2590,7 @@ class OutputPage extends ContextSource { public function showLagWarning( $lag ) { $config = $this->getConfig(); if ( $lag >= $config->get( 'SlaveLagWarning' ) ) { + $lag = floor( $lag ); // floor to avoid nano seconds to display $message = $lag < $config->get( 'SlaveLagCritical' ) ? 'lag-warn-normal' : 'lag-warn-high'; @@ -2704,26 +2718,32 @@ class OutputPage extends ContextSource { 'user.styles', 'user.cssprefs', ] ); + $this->getSkin()->setupSkinUserCss( $this ); // 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; } - if ( $name === 'site.styles' ) { - // HACK: Technically, 'site.styles' isn't in a separate request group. - // But, in order to ensure its styles are in the right position, - // pretend it's in a group called 'site'. - $group = 'site'; - } + $group = $module->getGroup(); if ( isset( $exemptGroups[$group] ) ) { $exemptStates[$name] = 'ready'; if ( !$module->isKnownEmpty( $context ) ) { @@ -2738,12 +2758,17 @@ class OutputPage extends ContextSource { ); $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() ); @@ -2785,8 +2810,8 @@ class OutputPage extends ContextSource { // 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' ] ); } @@ -2941,12 +2966,14 @@ class OutputPage extends ContextSource { } } - $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 ); } @@ -3064,8 +3091,8 @@ class OutputPage extends ContextSource { 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. @@ -3668,7 +3695,7 @@ class OutputPage extends ContextSource { 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