Merge "Http::getProxy() method to get proxy configuration"
[lhc/web/wiklou.git] / includes / libs / CSSMin.php
index 5a8c4c7..2f2faed 100644 (file)
@@ -45,7 +45,7 @@ class CSSMin {
        /* Protected Static Members */
 
        /** @var array List of common image files extensions and MIME-types */
-       protected static $mimeTypes = array(
+       protected static $mimeTypes = [
                'gif' => 'image/gif',
                'jpe' => 'image/jpeg',
                'jpeg' => 'image/jpeg',
@@ -55,49 +55,21 @@ class CSSMin {
                'tiff' => 'image/tiff',
                'xbm' => 'image/x-xbitmap',
                'svg' => 'image/svg+xml',
-       );
+       ];
 
        /* Static Methods */
 
        /**
-        * Gets a list of local file paths which are referenced in a CSS style sheet.
-        *
-        * If you wish non-existent files to be listed too, use getAllLocalFileReferences().
-        *
-        * For backwards-compatibility, if the second parameter is not given or null,
-        * this function will return an empty array instead of erroring out.
-        *
-        * @param string $source CSS stylesheet source to process
-        * @param string $path File path where the source was read from
-        * @return array List of local file references
-        */
-       public static function getLocalFileReferences( $source, $path = null ) {
-               if ( $path === null ) {
-                       return array();
-               }
-
-               $files = self::getAllLocalFileReferences( $source, $path );
-
-               // Skip non-existent files
-               $files = array_filter( $files, function ( $file ) {
-                       return file_exists( $file );
-               } );
-
-               return $files;
-       }
-
-       /**
-        * Gets a list of local file paths which are referenced in a CSS style sheet, including
-        * non-existent files.
+        * Get a list of local files referenced in a stylesheet (includes non-existent files).
         *
         * @param string $source CSS stylesheet source to process
         * @param string $path File path where the source was read from
         * @return array List of local file references
         */
-       public static function getAllLocalFileReferences( $source, $path ) {
+       public static function getLocalFileReferences( $source, $path ) {
                $stripped = preg_replace( '/' . self::COMMENT_REGEX . '/s', '', $source );
                $path = rtrim( $path, '/' ) . '/';
-               $files = array();
+               $files = [];
 
                $rFlags = PREG_OFFSET_CAPTURE | PREG_SET_ORDER;
                if ( preg_match_all( '/' . self::URL_REGEX . '/', $stripped, $matches, $rFlags ) ) {
@@ -180,6 +152,25 @@ class CSSMin {
                return false;
        }
 
+       /**
+        * Serialize a string (escape and quote) for use as a CSS string value.
+        * http://www.w3.org/TR/2013/WD-cssom-20131205/#serialize-a-string
+        *
+        * @param string $value
+        * @return string
+        * @throws Exception
+        */
+       public static function serializeStringValue( $value ) {
+               if ( strstr( $value, "\0" ) ) {
+                       throw new Exception( "Invalid character in CSS string" );
+               }
+               $value = strtr( $value, [ '\\' => '\\\\', '"' => '\\"' ] );
+               $value = preg_replace_callback( '/[\x01-\x1f\x7f-\x9f]/', function ( $match ) {
+                       return '\\' . base_convert( ord( $match[0] ), 10, 16 ) . ' ';
+               }, $value );
+               return '"' . $value . '"';
+       }
+
        /**
         * @param $file string
         * @return bool|string
@@ -220,7 +211,7 @@ class CSSMin {
                if ( preg_match( '!^[\w\d:@/~.%+;,?&=-]+$!', $url ) ) {
                        return "url($url)";
                } else {
-                       return 'url("' . strtr( $url, array( '\\' => '\\\\', '"' => '\\"' ) ) . '")';
+                       return 'url("' . strtr( $url, [ '\\' => '\\\\', '"' => '\\"' ] ) . '")';
                }
        }
 
@@ -258,7 +249,7 @@ class CSSMin {
                // Replace all comments by a placeholder so they will not interfere with the remapping.
                // Warning: This will also catch on anything looking like the start of a comment between
                // quotation marks (e.g. "foo /* bar").
-               $comments = array();
+               $comments = [];
 
                $pattern = '/(?!' . CSSMin::EMBED_REGEX . ')(' . CSSMin::COMMENT_REGEX . ')/s';
 
@@ -285,7 +276,17 @@ class CSSMin {
                                // Check for global @embed comment and remove it. Allow other comments to be present
                                // before @embed (they have been replaced with placeholders at this point).
                                $embedAll = false;
-                               $rule = preg_replace( '/^((?:\s+|' . CSSMin::PLACEHOLDER . '(\d+)x)*)' . CSSMin::EMBED_REGEX . '\s*/', '$1', $rule, 1, $embedAll );
+                               $rule = preg_replace(
+                                       '/^((?:\s+|' .
+                                               CSSMin::PLACEHOLDER .
+                                               '(\d+)x)*)' .
+                                               CSSMin::EMBED_REGEX .
+                                               '\s*/',
+                                       '$1',
+                                       $rule,
+                                       1,
+                                       $embedAll
+                               );
 
                                // Build two versions of current rule: with remapped URLs
                                // and with embedded data: URIs (where possible).
@@ -303,7 +304,7 @@ class CSSMin {
 
                                if ( $embedData ) {
                                        // Remember the occurring MIME types to avoid fallbacks when embedding some files.
-                                       $mimeTypes = array();
+                                       $mimeTypes = [];
 
                                        $ruleWithEmbedded = preg_replace_callback(
                                                $pattern,
@@ -320,7 +321,7 @@ class CSSMin {
                                                        $url = $match['file'] . $match['query'];
                                                        $file = $local . $match['file'];
                                                        if (
-                                                               !CSSMin::isRemoteUrl( $url ) && !CSSMin::isLocalUrl( $url )
+                                                               !self::isRemoteUrl( $url ) && !self::isLocalUrl( $url )
                                                                && file_exists( $file )
                                                        ) {
                                                                $mimeTypes[ CSSMin::getMimeType( $file ) ] = true;
@@ -332,7 +333,7 @@ class CSSMin {
                                        );
 
                                        // Are all referenced images SVGs?
-                                       $needsEmbedFallback = $mimeTypes !== array( 'image/svg+xml' => true );
+                                       $needsEmbedFallback = $mimeTypes !== [ 'image/svg+xml' => true ];
                                }
 
                                if ( !$embedData || $ruleWithEmbedded === $ruleWithRemapped ) {
@@ -362,11 +363,10 @@ class CSSMin {
        /**
         * Is this CSS rule referencing a remote URL?
         *
-        * @private Until we require PHP 5.5 and we can access self:: from closures.
         * @param string $maybeUrl
         * @return bool
         */
-       public static function isRemoteUrl( $maybeUrl ) {
+       protected static function isRemoteUrl( $maybeUrl ) {
                if ( substr( $maybeUrl, 0, 2 ) === '//' || parse_url( $maybeUrl, PHP_URL_SCHEME ) ) {
                        return true;
                }
@@ -376,11 +376,10 @@ class CSSMin {
        /**
         * Is this CSS rule referencing a local URL?
         *
-        * @private Until we require PHP 5.5 and we can access self:: from closures.
         * @param string $maybeUrl
         * @return bool
         */
-       public static function isLocalUrl( $maybeUrl ) {
+       protected static function isLocalUrl( $maybeUrl ) {
                if ( $maybeUrl !== '' && $maybeUrl[0] === '/' && !self::isRemoteUrl( $maybeUrl ) ) {
                        return true;
                }
@@ -422,15 +421,19 @@ class CSSMin {
                        // Path to the actual file on the filesystem
                        $localFile = "{$local}/{$file}";
                        if ( file_exists( $localFile ) ) {
-                               // Add version parameter as the first five hex digits
-                               // of the MD5 hash of the file's contents.
-                               $url .= '?' . substr( md5_file( $localFile ), 0, 5 );
                                if ( $embed ) {
                                        $data = self::encodeImageAsDataURI( $localFile );
                                        if ( $data !== false ) {
                                                return $data;
                                        }
                                }
+                               if ( method_exists( 'OutputPage', 'transformFilePath' ) ) {
+                                       $url = OutputPage::transformFilePath( $remote, $local, $file );
+                               } else {
+                                       // Add version parameter as the first five hex digits
+                                       // of the MD5 hash of the file's contents.
+                                       $url .= '?' . substr( md5_file( $localFile ), 0, 5 );
+                               }
                        }
                        // If any of these conditions failed (file missing, we don't want to embed it
                        // or it's not embeddable), return the URL (possibly with ?timestamp part)
@@ -450,9 +453,9 @@ class CSSMin {
        public static function minify( $css ) {
                return trim(
                        str_replace(
-                               array( '; ', ': ', ' {', '{ ', ', ', '} ', ';}' ),
-                               array( ';', ':', '{', '{', ',', '}', '}' ),
-                               preg_replace( array( '/\s+/', '/\/\*.*?\*\//s' ), array( ' ', '' ), $css )
+                               [ '; ', ': ', ' {', '{ ', ', ', '} ', ';}' ],
+                               [ ';', ':', '{', '{', ',', '}', '}' ],
+                               preg_replace( [ '/\s+/', '/\/\*.*?\*\//s' ], [ ' ', '' ], $css )
                        )
                );
        }