PluginProbe
Autoptimize / 0.5
Autoptimize v0.5
2.2.2 2.3.0 2.3.1 2.3.2 2.3.3 2.3.4 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.5.0 2.5.1 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 2.7.8 All 107 releases
autoptimize / classes / autoptimizeStyles.php

autoptimizeStyles.php in Autoptimize 0.5, at classes/autoptimizeStyles.php

253 lines 6.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 class autoptimizeStyles extends autoptimizeBase
3 {
4 private $css = array();
5 private $csscode = array();
6 private $url = array();
7 private $restofcontent = '';
8
9 //Reads the page and collects style tags
10 public function read($justhead)
11 {
12 //Remove everything that's not the header
13 if($justhead == true)
14 {
15 $content = explode('</head>',$this->content,2);
16 $this->content = $content[0].'</head>';
17 $this->restofcontent = $content[1];
18 }
19
20 //Save IE hacks
21 $this->content = preg_replace('#(<\!--\[if.*\]>.*<\!\[endif\]-->)#Usie',
22 '\'%%IEHACK%%\'.base64_encode("$1").\'%%IEHACK%%\'',$this->content);
23
24 //Get <style> and <link>
25 if(preg_match_all('#(<style[^>]*>.*</style>)|(<link[^>]*text/css[^>]*>)#Usmi',$this->content,$matches))
26 {
27 foreach($matches[0] as $tag)
28 {
29 if(preg_match('#<link.*href=("|\')(.*)("|\')#Usmi',$tag,$source))
30 {
31 //<link>
32 $url = current(explode('?',$source[2],2));
33 $path = $this->getpath($url);
34 $media = array('all');
35
36 if($path !==false && preg_match('#\.css$#',$path))
37 {
38 //Good link
39 //Get the media
40 if(strpos($tag,'media=')!==false)
41 {
42 $medias = preg_replace('#^.*media=(?:"|\')(.*)(?:"|\').*$#U','$1',$tag);
43 $medias = explode(',',$medias);
44 $media = array();
45 foreach($medias as $elem)
46 {
47 $media[] = current(explode(' ',trim($elem),2));
48 }
49 }
50
51 $this->css[] = array($media,$path);
52 }else{
53 //Link is dynamic (.php etc)
54 $tag = '';
55 }
56 }else{
57 //<style>
58 preg_match('#<style.*>(.*)</style>#Usmi',$tag,$code);
59 $code = preg_replace('#^.*<!\[CDATA\[(?:\s*\*/)?(.*)(?://|/\*)\s*?\]\]>.*$#sm','$1',$code[1]);
60 $this->css[] = array('all','INLINE;'.$code);
61 }
62
63 //Remove the original style tag
64 $this->content = str_replace($tag,'',$this->content);
65 }
66
67 return true;
68 }
69
70 //No styles :(
71 return false;
72 }
73
74 //Joins and optimizes CSS
75 public function minify()
76 {
77 foreach($this->css as $group)
78 {
79 list($media,$css) = $group;
80 if(preg_match('#^INLINE;#',$css))
81 {
82 //<style>
83 $css = preg_replace('#^INLINE;#','',$css);
84 $css = $this->fixurls(ABSPATH.'/index.php',$css);
85 if(!isset($this->csscode['all']))
86 $this->csscode['all'] = '';
87 $this->csscode['all'] .= "\n/*FILESTART*/".$css;
88 }else{
89 //<link>
90 if($css !== false && file_exists($css) && is_readable($css))
91 {
92 $css = $this->fixurls($css,file_get_contents($css));
93 foreach($media as $elem)
94 {
95 if(!isset($this->csscode[$elem]))
96 $this->csscode[$elem] = '';
97 $this->csscode[$elem] .= "\n/*FILESTART*/".$css;
98 }
99 }/*else{
100 //Couldn't read CSS. Maybe getpath isn't working?
101 }*/
102 }
103 }
104
105 //Check for duplicate code
106 $md5list = array();
107 $tmpcss = $this->csscode;
108 foreach($tmpcss as $media => $code)
109 {
110 $md5sum = md5($code);
111 $medianame = $media;
112 foreach($md5list as $med => $sum)
113 {
114 //If same code
115 if($sum === $md5sum)
116 {
117 //Add the merged code
118 $medianame = $med.', '.$media;
119 $this->csscode[$medianame] = $code;
120 $md5list[$medianame] = $md5list[$med];
121 unset($this->csscode[$med], $this->csscode[$media]);
122 unset($md5list[$med]);
123 }
124 }
125 $md5list[$medianame] = $md5sum;
126 }
127 unset($tmpcss);
128
129 //Manage @imports, while is for recursive import management
130 foreach($this->csscode as &$thiscss)
131 {
132 //Flag to trigger import reconstitution
133 $fiximports = false;
134 while(preg_match_all('#@import.*(?:;|$)#Um',$thiscss,$matches))
135 {
136 foreach($matches[0] as $import)
137 {
138 $url = trim(preg_replace('#.+((?:https?|ftp)://.*\.css)(?:\s|"|\').+#','$1',$import)," \t\n\r\0\x0B\"'");
139 $path = $this->getpath($url);
140 if(file_exists($path) && is_readable($path))
141 {
142 $code = $this->fixurls($path,file_get_contents($path));
143 /*$media = preg_replace('#^.*(?:\)|"|\')(.*)(?:\s|;).*$#','$1',$import);
144 $media = array_map('trim',explode(' ',$media));
145 if(empty($media))
146 {
147 $thiscss = [...] (Line under)
148 }else{
149 //media in @import - how should I handle these?
150 //TODO: Infinite recursion!
151 }*/
152 $thiscss = preg_replace('#(/\*FILESTART\*/.*)'.preg_quote($import,'#').'#Us',$code.'$1',$thiscss);
153 }else{
154 //getpath is not working?
155 //Encode so preg_match doesn't see it
156 $thiscss = str_replace($import,'/*IMPORT*/'.base64_encode($import).'/*IMPORT*/',$thiscss);
157 $fiximports = true;
158 }
159 }
160 }
161
162 //Recover imports
163 if($fiximports)
164 {
165 $thiscss = preg_replace('#/\*IMPORT\*/(.*)/\*IMPORT\*/#Use','base64_decode("$1")',$thiscss);
166 }
167 }
168 unset($thiscss);
169
170 //$this->csscode has all the uncompressed code now.
171 if(class_exists('Minify_CSS_Compressor'))
172 {
173 foreach($this->csscode as &$code)
174 {
175 $code = trim(Minify_CSS_Compressor::process($code));
176 }
177 unset($code);
178 return true;
179 }
180
181 return false;
182 }
183
184 //Caches the CSS in uncompressed, deflated and gzipped form.
185 public function cache()
186 {
187 foreach($this->csscode as $media => $code)
188 {
189 $md5 = md5($code);
190 $cache = new autopimizeCache(WP_PLUGIN_DIR.'/autoptimize/cache/',$md5);
191 if(!$cache->check())
192 {
193 //Cache our code
194 $cache->cache($code,'text/css');
195 }
196 $this->url[$media] = WP_PLUGIN_URL.'/autoptimize/cache/'.$cache->getname();
197 }
198 }
199
200 //Returns the content
201 public function getcontent()
202 {
203 //Restore IE hacks
204 $this->content = preg_replace('#%%IEHACK%%(.*)%%IEHACK%%#Usie','base64_decode("$1")',$this->content);
205
206 //Restore the full content
207 if(!empty($this->restofcontent))
208 {
209 $this->content .= $this->restofcontent;
210 $this->restofcontent = '';
211 }
212
213 //Add the new stylesheets
214 foreach($this->url as $media => $url)
215 {
216 $this->content = str_replace('</head>','<link type="text/css" media="'.$media.'" href="'.$url.'" rel="stylesheet" /></head>',$this->content);
217 }
218
219 //Return the modified stylesheet
220 return $this->content;
221 }
222
223 private function fixurls($file,$code)
224 {
225 $file = str_replace(ABSPATH,'/',$file); //Sth like /wp-content/file.css
226 $dir = dirname($file); //Like /wp-content
227
228 if(preg_match_all('#url\((.*)\)#Usi',$code,$matches))
229 {
230 $replace = array();
231 foreach($matches[1] as $url)
232 {
233 //Remove quotes
234 $url = trim($url," \t\n\r\0\x0B\"'");
235 if(substr($url,0,1)=='/' || preg_match('#^(https?|ftp)://#i',$url))
236 {
237 //URL is absolute
238 continue;
239 }else{
240 //relative URL. Let's fix it!
241 $newurl = get_settings('home').str_replace('//','/',$dir.'/'.$url); //http://yourblog.com/wp-content/../image.png
242 $replace[$url] = $newurl;
243 }
244 }
245
246 //Do the replacing here to avoid breaking URLs
247 $code = str_replace(array_keys($replace),array_values($replace),$code);
248 }
249
250 return $code;
251 }
252 }
253