Merge "Use LinkTarget in TitleValue only methods"
[lhc/web/wiklou.git] / includes / libs / CSSMin.php
index 2c90431..246de75 100644 (file)
@@ -60,13 +60,15 @@ class CSSMin {
        /* Static Methods */
 
        /**
-        * Gets a list of local file paths which are referenced in a CSS style sheet
+        * Gets a list of local file paths which are referenced in a CSS style sheet.
         *
-        * This function will always return an empty array if the second parameter is not given or null
-        * for backwards-compatibility.
+        * If you wish non-existent files to be listed too, use getAllLocalFileReferences().
         *
-        * @param string $source CSS data to remap
-        * @param string $path File path where the source was read from (optional)
+        * 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 ) {
@@ -74,11 +76,31 @@ class CSSMin {
                        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.
+        *
+        * @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 ) {
+               $stripped = preg_replace( '/' . self::COMMENT_REGEX . '/s', '', $source );
                $path = rtrim( $path, '/' ) . '/';
                $files = array();
 
                $rFlags = PREG_OFFSET_CAPTURE | PREG_SET_ORDER;
-               if ( preg_match_all( '/' . self::URL_REGEX . '/', $source, $matches, $rFlags ) ) {
+               if ( preg_match_all( '/' . self::URL_REGEX . '/', $stripped, $matches, $rFlags ) ) {
                        foreach ( $matches as $match ) {
                                $url = $match['file'][0];
 
@@ -87,13 +109,7 @@ class CSSMin {
                                        break;
                                }
 
-                               $file = $path . $url;
-                               // Skip non-existent files
-                               if ( file_exists( $file ) ) {
-                                       break;
-                               }
-
-                               $files[] = $file;
+                               $files[] = $path . $url;
                        }
                }
                return $files;
@@ -164,6 +180,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, array( '\\' => '\\\\', '"' => '\\"' ) );
+               $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
@@ -269,7 +304,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).
@@ -406,15 +451,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)