Merge "objectcache: fix some makeKey/makeGlobalKey IDEA warnings"
[lhc/web/wiklou.git] / includes / media / SVG.php
index 2bb6d13..2b13893 100644 (file)
@@ -20,6 +20,7 @@
  * @file
  * @ingroup Media
  */
+use Wikimedia\ScopedCallback;
 
 /**
  * Handler for SVG images.
@@ -96,19 +97,50 @@ class SvgHandler extends ImageHandler {
                        if ( isset( $metadata['translations'] ) ) {
                                foreach ( $metadata['translations'] as $lang => $langType ) {
                                        if ( $langType === SVGReader::LANG_FULL_MATCH ) {
-                                               $langList[] = $lang;
+                                               $langList[] = strtolower( $lang );
                                        }
                                }
                        }
                }
-               return $langList;
+               return array_unique( $langList );
        }
 
        /**
-        * What language to render file in if none selected.
+        * SVG's systemLanguage matching rules state:
+        * 'The `systemLanguage` attribute ... [e]valuates to "true" if one of the languages indicated
+        * by user preferences exactly equals one of the languages given in the value of this parameter,
+        * or if one of the languages indicated by user preferences exactly equals a prefix of one of
+        * the languages given in the value of this parameter such that the first tag character
+        * following the prefix is "-".'
         *
-        * @param File $file
-        * @return string Language code.
+        * Return the first element of $svgLanguages that matches $userPreferredLanguage
+        *
+        * @see https://www.w3.org/TR/SVG/struct.html#SystemLanguageAttribute
+        * @param string $userPreferredLanguage
+        * @param array $svgLanguages
+        * @return string|null
+        */
+       public function getMatchedLanguage( $userPreferredLanguage, array $svgLanguages ) {
+               foreach ( $svgLanguages as $svgLang ) {
+                       if ( strcasecmp( $svgLang, $userPreferredLanguage ) === 0 ) {
+                               return $svgLang;
+                       }
+                       $trimmedSvgLang = $svgLang;
+                       while ( strpos( $trimmedSvgLang, '-' ) !== false ) {
+                               $trimmedSvgLang = substr( $trimmedSvgLang, 0, strrpos( $trimmedSvgLang, '-' ) );
+                               if ( strcasecmp( $trimmedSvgLang, $userPreferredLanguage ) === 0 ) {
+                                       return $svgLang;
+                               }
+                       }
+               }
+               return null;
+       }
+
+       /**
+        * What language to render file in if none selected
+        *
+        * @param File $file Language code
+        * @return string
         */
        public function getDefaultRenderLanguage( File $file ) {
                return 'en';
@@ -125,7 +157,7 @@ class SvgHandler extends ImageHandler {
 
        /**
         * @param File $image
-        * @param array $params
+        * @param array &$params
         * @return bool
         */
        function normaliseParams( $image, &$params ) {
@@ -177,14 +209,14 @@ class SvgHandler extends ImageHandler {
 
                $metadata = $this->unpackMetadata( $image->getMetadata() );
                if ( isset( $metadata['error'] ) ) { // sanity check
-                       $err = wfMessage( 'svg-long-error', $metadata['error']['message'] )->text();
+                       $err = wfMessage( 'svg-long-error', $metadata['error']['message'] );
 
                        return new MediaTransformError( 'thumbnail_error', $clientWidth, $clientHeight, $err );
                }
 
                if ( !wfMkdirParents( dirname( $dstPath ), null, __METHOD__ ) ) {
                        return new MediaTransformError( 'thumbnail_error', $clientWidth, $clientHeight,
-                               wfMessage( 'thumbnail_dest_directory' )->text() );
+                               wfMessage( 'thumbnail_dest_directory' ) );
                }
 
                $srcPath = $image->getLocalRefPath();
@@ -195,7 +227,7 @@ class SvgHandler extends ImageHandler {
 
                        return new MediaTransformError( 'thumbnail_error',
                                $params['width'], $params['height'],
-                               wfMessage( 'filemissing' )->text()
+                               wfMessage( 'filemissing' )
                        );
                }
 
@@ -204,7 +236,17 @@ class SvgHandler extends ImageHandler {
                // https://git.gnome.org/browse/librsvg/commit/?id=f01aded72c38f0e18bc7ff67dee800e380251c8e
                $tmpDir = wfTempDir() . '/svg_' . wfRandomString( 24 );
                $lnPath = "$tmpDir/" . basename( $srcPath );
-               $ok = mkdir( $tmpDir, 0771 ) && symlink( $srcPath, $lnPath );
+               $ok = mkdir( $tmpDir, 0771 );
+               if ( !$ok ) {
+                       wfDebugLog( 'thumbnail',
+                               sprintf( 'Thumbnail failed on %s: could not create temporary directory %s',
+                                       wfHostname(), $tmpDir ) );
+                       return new MediaTransformError( 'thumbnail_error',
+                               $params['width'], $params['height'],
+                               wfMessage( 'thumbnail-temp-create' )->text()
+                       );
+               }
+               $ok = symlink( $srcPath, $lnPath );
                /** @noinspection PhpUnusedLocalVariableInspection */
                $cleaner = new ScopedCallback( function () use ( $tmpDir, $lnPath ) {
                        MediaWiki\suppressWarnings();
@@ -218,7 +260,7 @@ class SvgHandler extends ImageHandler {
                                        wfHostname(), $lnPath, $srcPath ) );
                        return new MediaTransformError( 'thumbnail_error',
                                $params['width'], $params['height'],
-                               wfMessage( 'thumbnail-temp-create' )->text()
+                               wfMessage( 'thumbnail-temp-create' )
                        );
                }
 
@@ -301,13 +343,13 @@ class SvgHandler extends ImageHandler {
        }
 
        /**
-        * @param File $file
+        * @param File|FSFile $file
         * @param string $path Unused
         * @param bool|array $metadata
         * @return array
         */
        function getImageSize( $file, $path, $metadata = false ) {
-               if ( $metadata === false ) {
+               if ( $metadata === false && $file instanceof File ) {
                        $metadata = $file->getMetadata();
                }
                $metadata = $this->unpackMetadata( $metadata );
@@ -355,7 +397,7 @@ class SvgHandler extends ImageHandler {
        }
 
        /**
-        * @param File $file
+        * @param File|FSFile $file
         * @param string $filename
         * @return string Serialised metadata
         */
@@ -468,7 +510,7 @@ class SvgHandler extends ImageHandler {
                        return ( $value > 0 );
                } elseif ( $name == 'lang' ) {
                        // Validate $code
-                       if ( $value === '' || !Language::isValidBuiltInCode( $value ) ) {
+                       if ( $value === '' || !Language::isValidCode( $value ) ) {
                                wfDebug( "Invalid user language code\n" );
 
                                return false;
@@ -488,8 +530,7 @@ class SvgHandler extends ImageHandler {
        public function makeParamString( $params ) {
                $lang = '';
                if ( isset( $params['lang'] ) && $params['lang'] !== 'en' ) {
-                       $params['lang'] = strtolower( $params['lang'] );
-                       $lang = "lang{$params['lang']}-";
+                       $lang = 'lang' . strtolower( $params['lang'] ) . '-';
                }
                if ( !isset( $params['width'] ) ) {
                        return false;
@@ -500,7 +541,7 @@ class SvgHandler extends ImageHandler {
 
        public function parseParamString( $str ) {
                $m = false;
-               if ( preg_match( '/^lang([a-z]+(?:-[a-z]+)*)-(\d+)px$/', $str, $m ) ) {
+               if ( preg_match( '/^lang([a-z]+(?:-[a-z]+)*)-(\d+)px$/i', $str, $m ) ) {
                        return [ 'width' => array_pop( $m ), 'lang' => $m[1] ];
                } elseif ( preg_match( '/^(\d+)px$/', $str, $m ) ) {
                        return [ 'width' => $m[1], 'lang' => 'en' ];