Use file width/height instead of metadata for getContentHeaders
[lhc/web/wiklou.git] / includes / media / MediaHandler.php
index 70a43f2..ec4d372 100644 (file)
@@ -100,21 +100,22 @@ abstract class MediaHandler {
         * @note If this is a multipage file, return the width and height of the
         *  first page.
         *
-        * @param File $image The image object, or false if there isn't one
+        * @param File|FSFile $image The image object, or false if there isn't one.
+        *   Warning, FSFile::getPropsFromPath might pass an FSFile instead of File (!)
         * @param string $path The filename
-        * @return array Follow the format of PHP getimagesize() internal function.
-        *   See http://www.php.net/getimagesize. MediaWiki will only ever use the
+        * @return array|bool Follow the format of PHP getimagesize() internal function.
+        *   See https://secure.php.net/getimagesize. MediaWiki will only ever use the
         *   first two array keys (the width and height), and the 'bits' associative
         *   key. All other array keys are ignored. Returning a 'bits' key is optional
-        *   as not all formats have a notion of "bitdepth".
+        *   as not all formats have a notion of "bitdepth". Returns false on failure.
         */
        abstract function getImageSize( $image, $path );
 
        /**
         * Get handler-specific metadata which will be saved in the img_metadata field.
         *
-        * @param File $image The image object, or false if there isn't one.
-        *   Warning, FSFile::getPropsFromPath might pass an (object)array() instead (!)
+        * @param File|FSFile $image The image object, or false if there isn't one.
+        *   Warning, FSFile::getPropsFromPath might pass an FSFile instead of File (!)
         * @param string $path The filename
         * @return string A string of metadata in php serialized form (Run through serialize())
         */
@@ -304,13 +305,11 @@ abstract class MediaHandler {
        }
 
        /**
-        * Get useful response headers for GET/HEAD requests for a file with the given metadata
-        *
-        * @param mixed $metadata Result of the getMetadata() function of this handler for a file
-        * @return array
-        */
+       * @deprecated since 1.30, use MediaHandler::getContentHeaders instead
+       */
        public function getStreamHeaders( $metadata ) {
-               return [];
+               wfDeprecated( __METHOD__, '1.30' );
+               return $this->getContentHeaders( $metadata );
        }
 
        /**
@@ -462,16 +461,16 @@ abstract class MediaHandler {
        /**
         * Get an array structure that looks like this:
         *
-        * array(
-        *    'visible' => array(
+        * [
+        *    'visible' => [
         *       'Human-readable name' => 'Human readable value',
         *       ...
-        *    ),
-        *    'collapsed' => array(
+        *    ],
+        *    'collapsed' => [
         *       'Human-readable name' => 'Human readable value',
         *       ...
-        *    )
-        * )
+        *    ]
+        * ]
         * The UI will format this into a table where the visible fields are always
         * visible, and the collapsed fields are optionally visible.
         *
@@ -761,7 +760,7 @@ abstract class MediaHandler {
         * @param string $cmd
         */
        protected function logErrorForExternalProcess( $retval, $err, $cmd ) {
-               # Keep error output limited (bug 57985)
+               # Keep error output limited (T59985)
                $errMessage = trim( substr( $err, 0, self::MAX_ERR_LOG_SIZE ) );
 
                wfDebugLog( 'thumbnail',
@@ -842,11 +841,11 @@ abstract class MediaHandler {
        /**
         * Gets configuration for the file warning message. Return value of
         * the following structure:
-        *   array(
+        *   [
         *     // Required, module with messages loaded for the client
         *     'module' => 'example.filewarning.messages',
         *     // Required, array of names of messages
-        *     'messages' => array(
+        *     'messages' => [
         *       // Required, main warning message
         *       'main' => 'example-filewarning-main',
         *       // Optional, header for warning dialog
@@ -855,10 +854,10 @@ abstract class MediaHandler {
         *       'footer' => 'example-filewarning-footer',
         *       // Optional, text for more-information link (see below)
         *       'info' => 'example-filewarning-info',
-        *     ),
+        *     ],
         *     // Optional, link for more information
         *     'link' => 'http://example.com',
-        *   )
+        *   ]
         *
         * Returns null if no warning is necessary.
         * @param File $file
@@ -867,4 +866,82 @@ abstract class MediaHandler {
        public function getWarningConfig( $file ) {
                return null;
        }
+
+       /**
+        * Converts a dimensions array about a potentially multipage document from an
+        * exhaustive list of ordered page numbers to a list of page ranges
+        * @param Array $pagesByDimensions
+        * @return String
+        * @since 1.30
+       */
+       public static function getPageRangesByDimensions( $pagesByDimensions ) {
+               $pageRangesByDimensions = [];
+
+               foreach ( $pagesByDimensions as $dimensions => $pageList ) {
+                       $ranges = [];
+                       $firstPage = $pageList[0];
+                       $lastPage = $firstPage - 1;
+
+                       foreach ( $pageList as $page ) {
+                               if ( $page > $lastPage + 1 ) {
+                                       if ( $firstPage != $lastPage ) {
+                                               $ranges[] = "$firstPage-$lastPage";
+                                       } else {
+                                               $ranges[] = "$firstPage";
+                                       }
+
+                                       $firstPage = $page;
+                               }
+
+                               $lastPage = $page;
+                       }
+
+                       if ( $firstPage != $lastPage ) {
+                               $ranges[] = "$firstPage-$lastPage";
+                       } else {
+                               $ranges[] = "$firstPage";
+                       }
+
+                       $pageRangesByDimensions[ $dimensions ] = $ranges;
+               }
+
+               $dimensionsString = [];
+               foreach ( $pageRangesByDimensions as $dimensions => $pageRanges ) {
+                       $dimensionsString[] = "$dimensions:" . implode( ',', $pageRanges );
+               }
+
+               return implode( '/', $dimensionsString );
+       }
+
+       /**
+       * Get useful response headers for GET/HEAD requests for a file with the given metadata
+       * @param $metadata Array Contains this handler's unserialized getMetadata() for a file
+       * @param $fallbackWidth int|null Width to fall back to if metadata doesn't have any
+       * @param $fallbackHeight int|null Height to fall back to if metadata doesn't have any
+       * @return Array
+       * @since 1.30
+       */
+       public function getContentHeaders( $metadata, $fallbackWidth = null, $fallbackHeight = null ) {
+               if ( !isset( $metadata['width'] ) ) {
+                       if ( is_null( $fallbackWidth ) ) {
+                               return [];
+                       }
+
+                       $metadata['width'] = $fallbackWidth;
+               }
+
+               if ( !isset( $metadata['height'] ) ) {
+                       if ( is_null( $fallbackHeight ) ) {
+                               return [];
+                       }
+
+                       $metadata['height'] = $fallbackHeight;
+               }
+
+               $dimensionString = $metadata['width'] . 'x' . $metadata['height'];
+               $pagesByDimensions = [ $dimensionString => [ 1 ] ];
+               $pageRangesByDimensions = MediaHandler::getPageRangesByDimensions( $pagesByDimensions );
+
+               return [ 'X-Content-Dimensions' => $pageRangesByDimensions ];
+       }
 }