Index: trunk/phase3/includes/libs/CSSMin.php |
— | — | @@ -24,9 +24,9 @@ |
25 | 25 | * @author Trevor Parscal |
26 | 26 | */ |
27 | 27 | class CSSMin { |
28 | | - |
| 28 | + |
29 | 29 | /* Constants */ |
30 | | - |
| 30 | + |
31 | 31 | /** |
32 | 32 | * Maximum file size to still qualify for in-line embedding as a data-URI |
33 | 33 | * |
— | — | @@ -34,9 +34,23 @@ |
35 | 35 | * result in a 1/3 increase in size. |
36 | 36 | */ |
37 | 37 | const EMBED_SIZE_LIMIT = 24576; |
38 | | - |
| 38 | + |
| 39 | + /* Protected Static Members */ |
| 40 | + |
| 41 | + /** @var array List of common image files extensions and mime-types */ |
| 42 | + protected static $mimeTypes = array( |
| 43 | + 'gif' => 'image/gif', |
| 44 | + 'jpe' => 'image/jpeg', |
| 45 | + 'jpeg' => 'image/jpeg', |
| 46 | + 'jpg' => 'image/jpeg', |
| 47 | + 'png' => 'image/png', |
| 48 | + 'tif' => 'image/tiff', |
| 49 | + 'tiff' => 'image/tiff', |
| 50 | + 'xbm' => 'image/x-xbitmap', |
| 51 | + ); |
| 52 | + |
39 | 53 | /* Static Methods */ |
40 | | - |
| 54 | + |
41 | 55 | /** |
42 | 56 | * Gets a list of local file paths which are referenced in a CSS style sheet |
43 | 57 | * |
— | — | @@ -47,7 +61,6 @@ |
48 | 62 | public static function getLocalFileReferences( $source, $path = null ) { |
49 | 63 | $pattern = '/url\([\'"]?(?<file>[^\?\)\:]*)\??[^\)]*[\'"]?\)/'; |
50 | 64 | $files = array(); |
51 | | - |
52 | 65 | if ( preg_match_all( $pattern, $source, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER ) ) { |
53 | 66 | foreach ( $matches as $match ) { |
54 | 67 | $file = ( isset( $path ) ? rtrim( $path, '/' ) . '/' : '' ) . "{$match['file'][0]}"; |
— | — | @@ -58,10 +71,9 @@ |
59 | 72 | } |
60 | 73 | } |
61 | 74 | } |
62 | | - |
63 | 75 | return $files; |
64 | 76 | } |
65 | | - |
| 77 | + |
66 | 78 | /** |
67 | 79 | * Remaps CSS URL paths and automatically embeds data URIs for URL rules preceded by an /* @embed * / comment |
68 | 80 | * |
— | — | @@ -70,26 +82,36 @@ |
71 | 83 | * @return string Remapped CSS data |
72 | 84 | */ |
73 | 85 | public static function remap( $source, $path, $embed = true ) { |
74 | | - |
75 | 86 | $pattern = '/((?<embed>\s*\/\*\s*\@embed\s*\*\/)(?<rule>[^\;\}]*))?url\([\'"]?(?<file>[^\?\)\:]*)\??[^\)]*[\'"]?\)(?<extra>[^;]*)[\;]?/'; |
76 | 87 | $offset = 0; |
77 | | - |
78 | 88 | while ( preg_match( $pattern, $source, $match, PREG_OFFSET_CAPTURE, $offset ) ) { |
79 | 89 | // Shortcuts |
80 | 90 | $embed = $match['embed'][0]; |
81 | 91 | $rule = $match['rule'][0]; |
82 | 92 | $extra = $match['extra'][0]; |
83 | 93 | $file = "{$path}/{$match['file'][0]}"; |
84 | | - |
85 | 94 | // Only proceed if we can access the file |
86 | 95 | if ( file_exists( $file ) ) { |
87 | 96 | // Add version parameter as a time-stamp in ISO 8601 format, using Z for the timezone, meaning GMT |
88 | 97 | $url = "{$file}?" . gmdate( 'Y-m-d\TH:i:s\Z', round( filemtime( $file ), -2 ) ); |
89 | | - |
| 98 | + // If we the mime-type can't be determined, no embedding will take place |
| 99 | + $type = false; |
| 100 | + // Try a couple of different ways to get the mime-type of a file, in order of preference |
| 101 | + if ( function_exists( 'finfo_file' ) && function_exists( 'finfo_open' ) ) { |
| 102 | + // As of PHP 5.3, this is how you get the mime-type of a file; it uses the Fileinfo PECL extension |
| 103 | + $type = finfo_file( finfo_open( FILEINFO_MIME_TYPE ), $file ); |
| 104 | + } else if ( function_exists( 'mime_content_type' ) ) { |
| 105 | + // Before this was deprecated in PHP 5.3, this used to be how you get the mime-type of a file |
| 106 | + $type = mime_content_type( $file ); |
| 107 | + } else { |
| 108 | + // Worst-case scenario has happend, use the file extension to infer the mime-type |
| 109 | + $ext = strtolower( pathinfo( $file, PATHINFO_EXTENSION ) ); |
| 110 | + if ( isset( self::$mimeTypes[$ext] ) ) { |
| 111 | + $type = self::$mimeTypes[$ext]; |
| 112 | + } |
| 113 | + } |
90 | 114 | // Detect when URLs were preceeded with embed tags, and also verify file size is below the limit |
91 | | - if ( $embed && $match['embed'][1] > 0 && filesize( $file ) < self::EMBED_SIZE_LIMIT ) { |
92 | | - // If we ever get to PHP 5.3, we should use the Fileinfo extension instead of mime_content_type |
93 | | - $type = mime_content_type( $file ); |
| 115 | + if ( $embed && $type && $match['embed'][1] > 0 && filesize( $file ) < self::EMBED_SIZE_LIMIT ) { |
94 | 116 | // Strip off any trailing = symbols (makes browsers freak out) |
95 | 117 | $data = base64_encode( file_get_contents( $file ) ); |
96 | 118 | // Build 2 CSS properties; one which uses a base64 encoded data URI in place of the @embed |
— | — | @@ -110,10 +132,9 @@ |
111 | 133 | // Move the offset to the end of the match, leaving it alone |
112 | 134 | $offset = $match[0][1] + strlen( $match[0][0] ); |
113 | 135 | } |
114 | | - |
115 | 136 | return $source; |
116 | 137 | } |
117 | | - |
| 138 | + |
118 | 139 | /** |
119 | 140 | * Removes whitespace from CSS data |
120 | 141 | * |