X-Git-Url: http://git.cyclocoop.org/%7B%24www_url%7Dadmin/compta/pie.php?a=blobdiff_plain;f=includes%2FOutputPage.php;h=551141ec031da5e70c12f1a9899197be97bfc4ef;hb=85fcc8b254e661690a21ab187101b10ca79ac072;hp=a25ea9cf2f79fb6152b72a31e1c675d940ffcbc8;hpb=05468d1009cc1e3270b7eb242593f188f759403b;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/OutputPage.php b/includes/OutputPage.php index a25ea9cf2f..551141ec03 100644 --- a/includes/OutputPage.php +++ b/includes/OutputPage.php @@ -302,6 +302,11 @@ class OutputPage extends ContextSource { /** @var array Profiling data */ private $limitReportJSData = []; + /** + * Link: header contents + */ + private $mLinkHeader = []; + /** * Constructor for OutputPage. This should not be called directly. * Instead a new RequestContext should be created and it will implicitly create @@ -2105,6 +2110,28 @@ class OutputPage extends ContextSource { return 'Vary: ' . implode( ', ', array_keys( $this->mVaryHeader ) ); } + /** + * Add an HTTP Link: header + * + * @param string $header Header value + */ + public function addLinkHeader( $header ) { + $this->mLinkHeader[] = $header; + } + + /** + * Return a Link: header. Based on the values of $mLinkHeader. + * + * @return string + */ + public function getLinkHeader() { + if ( !$this->mLinkHeader ) { + return false; + } + + return 'Link: ' . implode( ',', $this->mLinkHeader ); + } + /** * Get a complete Key header * @@ -2361,6 +2388,12 @@ class OutputPage extends ContextSource { // jQuery etc. can work correctly. $response->header( 'X-UA-Compatible: IE=Edge' ); + $this->addLogoPreloadLinkHeaders(); + $linkHeader = $this->getLinkHeader(); + if ( $linkHeader ) { + $response->header( $linkHeader ); + } + // Prevent framing, if requested $frameOptions = $this->getFrameOptions(); if ( $frameOptions ) { @@ -3965,4 +3998,82 @@ class OutputPage extends ContextSource { 'mediawiki.widgets.styles', ] ); } + + /** + * Add Link headers for preloading the wiki's logo. + * + * @since 1.26 + */ + protected function addLogoPreloadLinkHeaders() { + $logo = $this->getConfig()->get( 'Logo' ); // wgLogo + $logoHD = $this->getConfig()->get( 'LogoHD' ); // wgLogoHD + + $tags = []; + $logosPerDppx = []; + $logos = []; + + $logosPerDppx['1.0'] = $logo; + + if ( !$logoHD ) { + // No media queries required if we only have one variant + $this->addLinkHeader( '<' . $logo . '>;rel=preload;as=image' ); + return; + } + + foreach ( $logoHD as $dppx => $src ) { + // Only 1.5x and 2x are supported + // Note: Keep in sync with ResourceLoaderSkinModule + if ( in_array( $dppx, [ '1.5x', '2x' ] ) ) { + // LogoHD uses a string 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 ); + + if ( $a == $b ) { + return 0; + } + // Sort from smallest to largest (e.g. 1x, 1.5x, 2x) + return ( $a < $b ) ? -1 : 1; + } ); + + 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 + ); + } + } }