PluginProbe
Powered Cache – Caching and Optimization for WordPress – Easily Improve PageSpeed & Web Vitals Score / 2.1
Powered Cache – Caching and Optimization for WordPress – Easily Improve PageSpeed & Web Vitals Score v2.1
trunk 1.0 1.0.1 1.1 1.1.1 1.1.2 1.2 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 2.0 2.0.1 2.0.2 2.0.3 2.0.4 2.1 2.1.1 2.1.2 2.2 2.2.1 All 69 releases
powered-cache / includes / classes / Optimizer / CSS.php

CSS.php in Powered Cache – Caching and Optimization for WordPress – Easily Improve PageSpeed & Web Vitals Score 2.1, at includes/classes/Optimizer/CSS.php

301 lines 7.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * CSS contact
4 *
5 * @package PoweredCache\Optimizer
6 */
7
8 //phpcs:disable Squiz.Commenting.VariableComment.Missing
9 //phpcs:disable Generic.Commenting.DocComment.MissingShort
10 //phpcs:disable Squiz.Commenting.FunctionComment.MissingParamName
11 //phpcs:disable Squiz.Commenting.FunctionComment.MissingParamTag
12
13 namespace PoweredCache\Optimizer;
14
15 use PoweredCache\CDN;
16 use \WP_Styles as WP_Styles;
17
18 /**
19 * Class CSS
20 */
21 class CSS extends WP_Styles {
22 private $old_styles;
23 public $allow_gzip_compression;
24 public $do_minify;
25 public $enable_cdn;
26
27 /**
28 * CSS constructor.
29 *
30 * @param object $styles WP_Styles
31 */
32 public function __construct( $styles ) {
33 if ( empty( $styles ) || ! ( $styles instanceof WP_Styles ) ) {
34 $this->old_styles = new WP_Styles();
35 } else {
36 $this->old_styles = $styles;
37 }
38
39 // Unset all the object properties except our private copy of the styles object.
40 // We have to unset everything so that the overload methods talk to $this->old_styles->whatever
41 // instead of $this->whatever.
42 foreach ( array_keys( get_object_vars( $this ) ) as $key ) {
43 if ( 'old_styles' === $key ) {
44 continue;
45 }
46 unset( $this->$key );
47 }
48 }
49
50 /**
51 * Prep items for concat
52 *
53 * @param bool $handles CSS handler
54 * @param bool $group CSS group
55 *
56 * @return string[]
57 */
58 public function do_items( $handles = false, $group = false ) {
59 $handles = false === $handles ? $this->queue : (array) $handles;
60 $stylesheets = array();
61 /**
62 * Filters site url
63 *
64 * @hook powered_cache_fo_site_url
65 *
66 * @param {string} $base_url Site URL.
67 *
68 * @return {string} New value.
69 * @since 2.0
70 */
71 $siteurl = apply_filters( 'powered_cache_fo_site_url', $this->base_url );
72 $this->all_deps( $handles );
73
74 $stylesheet_group_index = 0;
75 foreach ( $this->to_do as $key => $handle ) {
76 $obj = $this->registered[ $handle ];
77
78 if ( $this->enable_cdn ) { // since CDN replaces hostname, it breaks is_internal_url checks.
79 remove_filter( 'style_loader_src', array( CDN::factory(), 'cdn_url' ), PHP_INT_MAX );
80 }
81
82 $obj->src = apply_filters( 'style_loader_src', $obj->src, $obj->handle );
83
84 if ( $this->enable_cdn ) { // add filter back
85 add_filter( 'style_loader_src', array( CDN::factory(), 'cdn_url' ), PHP_INT_MAX );
86 }
87
88 // Core is kind of broken and returns "true" for src of "colors" handle
89 // http://core.trac.wordpress.org/attachment/ticket/16827/colors-hacked-fixed.diff
90 // http://core.trac.wordpress.org/ticket/20729
91 $css_url = $obj->src;
92 if ( 'colors' === $obj->handle && true === $css_url ) {
93 $css_url = wp_style_loader_src( $css_url, $obj->handle );
94 }
95
96 $css_url_parsed = wp_parse_url( $obj->src );
97 $extra = $obj->extra;
98
99 // Don't concat by default
100 $do_concat = false;
101
102 // Only try to concat static css files
103 if ( false !== strpos( $css_url_parsed['path'], '.css' ) ) {
104 $do_concat = true;
105 }
106
107 // Don't try to concat styles which are loaded conditionally (like IE stuff)
108 if ( isset( $extra['conditional'] ) ) {
109 $do_concat = false;
110 }
111
112 // Don't concat rtl stuff for now until concat supports it correctly
113 if ( 'rtl' === $this->text_direction && ! empty( $extra['rtl'] ) ) {
114 $do_concat = false;
115 }
116
117 // Don't try to concat externally hosted scripts
118 $is_internal_url = Helper::is_internal_url( $css_url, $siteurl );
119 if ( ! $is_internal_url ) {
120 $do_concat = false;
121 }
122
123 // Concat and canonicalize the paths only for
124 // existing scripts that aren't outside ABSPATH
125 $css_realpath = Helper::realpath( $css_url, $siteurl );
126 if ( ! $css_realpath || 0 !== strpos( $css_realpath, ABSPATH ) ) {
127 $do_concat = false;
128 } else {
129 $css_url_parsed['path'] = substr( $css_realpath, strlen( ABSPATH ) - 1 );
130 }
131
132 if ( Helper::is_excluded_css( $css_url ) ) {
133 $do_concat = false;
134 }
135
136 /**
137 * Allow plugins to disable concatenation of certain stylesheets.
138 *
139 * @hook powered_cache_fo_css_do_concat
140 *
141 * @param {boolean} $do_concat Contact status.
142 * @param {string} $handle Handle of registered CSS item.
143 *
144 * @return {boolean} New value.
145 * @since 2.0
146 */
147 $do_concat = apply_filters( 'powered_cache_fo_css_do_concat', $do_concat, $handle );
148
149 if ( true === $do_concat ) {
150 $media = $obj->args;
151 if ( empty( $media ) ) {
152 $media = 'all';
153 }
154 if ( ! isset( $stylesheets[ $stylesheet_group_index ] ) || ( isset( $stylesheets[ $stylesheet_group_index ] ) && ! is_array( $stylesheets[ $stylesheet_group_index ] ) ) ) {
155 $stylesheets[ $stylesheet_group_index ] = array();
156 }
157
158 $stylesheets[ $stylesheet_group_index ][ $media ][ $handle ] = $css_url_parsed['path'];
159 $this->done[] = $handle;
160 } else {
161 $stylesheet_group_index ++;
162 $stylesheets[ $stylesheet_group_index ]['noconcat'][] = $handle;
163 $stylesheet_group_index ++;
164 }
165 unset( $this->to_do[ $key ] );
166 }
167
168 foreach ( $stylesheets as $idx => $stylesheets_group ) {
169 foreach ( $stylesheets_group as $media => $css ) {
170 if ( 'noconcat' === $media ) {
171
172 foreach ( $css as $handle ) {
173 if ( $this->do_item( $handle, $group ) ) {
174 $this->done[] = $handle;
175 }
176 }
177 continue;
178 } elseif ( count( $css ) > 1 ) {
179 $paths = array_map(
180 function ( $url ) {
181 return ABSPATH . $url;
182 },
183 $css
184 );
185 $mtime = max( array_map( 'filemtime', $paths ) );
186 $path_str = implode( ',', $css ) . "?m={$mtime}";
187
188 if ( $this->allow_gzip_compression ) {
189 $path_64 = base64_encode( gzcompress( $path_str ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
190 if ( strlen( $path_str ) > ( strlen( $path_64 ) + 1 ) ) {
191 $path_str = '-' . $path_64;
192 }
193 }
194
195 $href = Helper::get_optimized_url( $path_str, $this->do_minify );
196 } else {
197 if ( $this->do_minify ) {
198 $href = Helper::get_optimized_url( current( $css ), $this->do_minify );
199 } else {
200 $href = $this->cache_bust_mtime( $siteurl . current( $css ), $siteurl );
201 }
202 }
203
204 $handles = array_keys( $css );
205 $css_tag = "<link rel='stylesheet' id='$media-css-$idx' href='$href' type='text/css' media='$media' />\n"; // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedStylesheet
206 /**
207 * Filters combined CSS tag.
208 *
209 * @hook powered_cache_fo_style_loader_tag
210 *
211 * @param {string} $css_tag CSS tag.
212 * @param {array} $handles The list of CSS handles.
213 * @param {string} $href CSS URL.
214 * @param {string} $media Media type.
215 *
216 * @return {string} New value.
217 * @since 2.0
218 */
219 echo apply_filters( 'powered_cache_fo_style_loader_tag', $css_tag, $handles, $href, $media ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
220 array_map( array( $this, 'print_inline_style' ), array_keys( $css ) );
221 }
222 }
223
224 return $this->done;
225 }
226
227 /**
228 * Bust cache
229 *
230 * @param string $url CSS URL
231 * @param string $siteurl Site URL
232 *
233 * @return string
234 */
235 public function cache_bust_mtime( $url, $siteurl ) {
236 if ( strpos( $url, '?m=' ) ) {
237 return $url;
238 }
239
240 $parts = wp_parse_url( $url );
241 if ( ! isset( $parts['path'] ) || empty( $parts['path'] ) ) {
242 return $url;
243 }
244
245 $file = Helper::realpath( $url, $siteurl );
246
247 $mtime = false;
248 if ( file_exists( $file ) ) {
249 $mtime = filemtime( $file );
250 }
251
252 if ( ! $mtime ) {
253 return $url;
254 }
255
256 if ( false === strpos( $url, '?' ) ) {
257 $q = '';
258 } else {
259 list( $url, $q ) = explode( '?', $url, 2 );
260 if ( strlen( $q ) ) {
261 $q = '&amp;' . $q;
262 }
263 }
264
265 return "$url?m={$mtime}g{$q}";
266 }
267
268 /**
269 * @param $key
270 *
271 * @return bool
272 */
273 public function __isset( $key ) {
274 return isset( $this->old_styles->$key );
275 }
276
277 /**
278 * @param $key
279 */
280 public function __unset( $key ) {
281 unset( $this->old_styles->$key );
282 }
283
284 /**
285 * @param $key
286 *
287 * @return mixed
288 */
289 public function &__get( $key ) {
290 return $this->old_styles->$key;
291 }
292
293 /**
294 * @param $key
295 * @param $value
296 */
297 public function __set( $key, $value ) {
298 $this->old_styles->$key = $value;
299 }
300 }
301