Breeze – WordPress Cache Plugin - Version 1.1.2

Version Description

  • Fix: Improved handling of exclusion of CSS and JS while Minification and Group Files options are enabled.
  • Fix: Allow wildcard (.*) based exclusion of pattern files/URIs in exclude JS and exclude CSS fields.
  • Fix: Increase the duration for leverage browser cacheable objects
Download this release

Release Info

Developer adeelkhan
Plugin Icon 128x128 Breeze – WordPress Cache Plugin
Version 1.1.2
Comparing to
See all releases

Code changes from version 1.1.1 to 1.1.2

breeze.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Plugin Name: Breeze
4
  * Description: Breeze is a WordPress cache plugin with extensive options to speed up your website. All the options including Varnish Cache are compatible with Cloudways hosting.
5
- * Version: 1.1.1
6
  * Text Domain: breeze
7
  * Domain Path: /languages
8
  * Author: Cloudways
@@ -36,7 +36,7 @@ defined('ABSPATH') || die('No direct script access allowed!');
36
  if (!defined('BREEZE_PLUGIN_DIR'))
37
  define('BREEZE_PLUGIN_DIR', plugin_dir_path(__FILE__));
38
  if (!defined('BREEZE_VERSION'))
39
- define('BREEZE_VERSION','1.1.1');
40
  if (!defined('BREEZE_SITEURL'))
41
  define('BREEZE_SITEURL', get_site_url());
42
  if (!defined('BREEZE_MINIFICATION_CACHE'))
2
  /**
3
  * Plugin Name: Breeze
4
  * Description: Breeze is a WordPress cache plugin with extensive options to speed up your website. All the options including Varnish Cache are compatible with Cloudways hosting.
5
+ * Version: 1.1.2
6
  * Text Domain: breeze
7
  * Domain Path: /languages
8
  * Author: Cloudways
36
  if (!defined('BREEZE_PLUGIN_DIR'))
37
  define('BREEZE_PLUGIN_DIR', plugin_dir_path(__FILE__));
38
  if (!defined('BREEZE_VERSION'))
39
+ define('BREEZE_VERSION','1.1.2');
40
  if (!defined('BREEZE_SITEURL'))
41
  define('BREEZE_SITEURL', get_site_url());
42
  if (!defined('BREEZE_MINIFICATION_CACHE'))
inc/breeze-configuration.php CHANGED
@@ -103,6 +103,14 @@ class Breeze_Configuration{
103
  $exclude_js = $this->string_convert_arr(sanitize_textarea_field($_POST['exclude-js']));
104
  $move_to_footer_js = $defer_js = array();
105
 
 
 
 
 
 
 
 
 
106
  if (!empty($_POST['move-to-footer-js'])) {
107
  foreach ($_POST['move-to-footer-js'] as $url) {
108
  if (trim($url) == '') continue;
@@ -228,17 +236,20 @@ class Breeze_Configuration{
228
  $args['content'] = 'SetEnv BREEZE_BROWSER_CACHE_ON 1' . PHP_EOL .
229
  '<IfModule mod_expires.c>' . PHP_EOL .
230
  ' ExpiresActive On' . PHP_EOL .
231
- ' ExpiresDefault A2592000' . PHP_EOL .
232
- ' ExpiresByType application/javascript "access plus 7 days"' . PHP_EOL .
233
- ' ExpiresByType text/javascript "access plus 7 days"' . PHP_EOL .
234
- ' ExpiresByType text/css "access plus 7 days"' . PHP_EOL .
235
- ' ExpiresByType image/jpeg "access plus 7 days"' . PHP_EOL .
236
- ' ExpiresByType image/png "access plus 7 days"' . PHP_EOL .
237
- ' ExpiresByType image/gif "access plus 7 days"' . PHP_EOL .
238
- ' ExpiresByType image/ico "access plus 7 days"' . PHP_EOL .
239
- ' ExpiresByType image/x-icon "access plus 7 days"' . PHP_EOL .
240
- ' ExpiresByType image/svg+xml "access plus 7 days"' . PHP_EOL .
241
- ' ExpiresByType image/bmp "access plus 7 days"' . PHP_EOL .
 
 
 
242
  '</IfModule>' . PHP_EOL;
243
 
244
  $args['conditions'] = array(
103
  $exclude_js = $this->string_convert_arr(sanitize_textarea_field($_POST['exclude-js']));
104
  $move_to_footer_js = $defer_js = array();
105
 
106
+ if(!empty($exclude_js)){
107
+ $exclude_js = array_unique($exclude_js);
108
+ }
109
+
110
+ if(!empty($exclude_css)){
111
+ $exclude_css = array_unique($exclude_css);
112
+ }
113
+
114
  if (!empty($_POST['move-to-footer-js'])) {
115
  foreach ($_POST['move-to-footer-js'] as $url) {
116
  if (trim($url) == '') continue;
236
  $args['content'] = 'SetEnv BREEZE_BROWSER_CACHE_ON 1' . PHP_EOL .
237
  '<IfModule mod_expires.c>' . PHP_EOL .
238
  ' ExpiresActive On' . PHP_EOL .
239
+ ' ExpiresByType image/gif "access 1 year"' . PHP_EOL .
240
+ ' ExpiresByType image/jpg "access 1 year"' . PHP_EOL .
241
+ ' ExpiresByType image/jpeg "access 1 year"' . PHP_EOL .
242
+ ' ExpiresByType image/png "access 1 year"' . PHP_EOL .
243
+ ' ExpiresByType image/x-icon "access 1 year"' . PHP_EOL .
244
+ ' ExpiresByType text/css "access 1 month"' . PHP_EOL .
245
+ ' ExpiresByType text/javascript "access 1 month"' . PHP_EOL .
246
+ ' ExpiresByType text/html "access 1 month"' . PHP_EOL .
247
+ ' ExpiresByType application/javascript "access 1 month"' . PHP_EOL .
248
+ ' ExpiresByType application/x-javascript "access 1 month"' . PHP_EOL .
249
+ ' ExpiresByType application/xhtml-xml "access 1 month"' . PHP_EOL .
250
+ ' ExpiresByType application/pdf "access 1 month"' . PHP_EOL .
251
+ ' ExpiresByType application/x-shockwave-flash "access 1 month"' . PHP_EOL .
252
+ ' ExpiresDefault "access 1 month"' . PHP_EOL .
253
  '</IfModule>' . PHP_EOL;
254
 
255
  $args['conditions'] = array(
inc/cache/purge-varnish.php CHANGED
@@ -1,295 +1,321 @@
1
- <?php
2
- /**
3
- * @copyright 2017 Cloudways https://www.cloudways.com
4
- *
5
- * Original development of this plugin by JoomUnited https://www.joomunited.com/
6
- *
7
- * This program is free software; you can redistribute it and/or modify
8
- * it under the terms of the GNU General Public License as published by
9
- * the Free Software Foundation; either version 2 of the License, or
10
- * (at your option) any later version.
11
- *
12
- * This program is distributed in the hope that it will be useful,
13
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- * GNU General Public License for more details.
16
- *
17
- * You should have received a copy of the GNU General Public License
18
- * along with this program; if not, write to the Free Software
19
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20
- */
21
- defined('ABSPATH') || die('No direct script access allowed!');
22
- class Breeze_PurgeVarnish {
23
- protected $blogId;
24
- protected $urlsPurge = array();
25
- protected $autoPurge = false;
26
- protected $actions = array(
27
- 'switch_theme', // After a theme is changed
28
- 'save_post', // Save a post
29
- 'deleted_post', // Delete a post
30
- 'edit_post', // Edit a post - includes leaving comments
31
- );
32
- protected $actionsNoId = array('switch_theme');
33
- public function __construct(){
34
- global $blog_id;
35
- $this->blogId = $blog_id;
36
- $settings = breeze_get_option( 'varnish_cache' );
37
- //storage config
38
- if(!empty($settings['auto-purge-varnish'])) $this->autoPurge = (int)$settings['auto-purge-varnish'];
39
- add_action('init', array($this, 'init'));
40
- }
41
- public function init()
42
- {
43
- //Push urlsPurge
44
- if($this->autoPurge){
45
- if (!empty($this->actions)) {
46
- //if enabled auto purge option , this action will start
47
- foreach ($this->actions as $action) {
48
- if (in_array($action, $this->actionsNoId)) {
49
- add_action($action, function () {
50
- array_push($this->urlsPurge, home_url() . '/?breeze');
51
- });
52
- } else {
53
- add_action($action, array($this, 'purge_post'));
54
- }
55
- }
56
- }
57
- //Pust urlsPurge after comment
58
- add_action('comment_post',array($this,'purge_post_on_comment'),10,3);
59
- add_action('wp_set_comment_status', array($this, 'purge_post_on_comment_status'), 10, 2);
60
- }
61
- //Execute Purge
62
- add_action('shutdown', array($this, 'breeze_execute_purge'));
63
- }
64
- /**
65
- * Execute Purge
66
- *
67
- */
68
- public function breeze_execute_purge()
69
- {
70
- $urlsPurge = array_unique($this->urlsPurge);
71
- if (!empty($urlsPurge)) {
72
- foreach ($urlsPurge as $url) {
73
- $this->purge_cache($url);
74
- }
75
- } else {
76
- $homepage = home_url().'/?breeze';
77
- if (isset($_REQUEST['breeze_action']) && $_REQUEST['breeze_action'] == 'breeze_settings') {
78
- if (isset($_POST['_breeze_nonce']) || wp_verify_nonce($_POST['_breeze_nonce'], 'breeze_settings')) {
79
- do_action('breeze_clear_all_cache');
80
- }
81
- }
82
- if(isset($_GET['breeze_purge']) && check_admin_referer('breeze_purge_cache')){
83
- //clear varnish cache
84
- $admin = new Breeze_Admin();
85
- $admin->breeze_clear_varnish();
86
- //clear static cache
87
- $size_cache = Breeze_Configuration::breeze_clean_cache();
88
- if((int)$size_cache > 0){
89
- echo '<div id="message-clear-cache-top" style="margin: 10px 0px 10px 0;padding: 10px;" class="notice notice-success" ><strong>'.__('Cache data has been purged: ','breeze') .$size_cache.__(' Kb static cache cleaned','breeze').'</strong></div>';
90
- }else{
91
- echo '<div id="message-clear-cache-top" style="margin: 10px 0px 10px 0;padding: 10px;" class="notice notice-success" ><strong>'.__('Cache data has been purged.','breeze').'</strong></div>';
92
- }
93
- }
94
- }
95
- }
96
- /**
97
- * Purge varnish cache
98
- *
99
- */
100
- public function purge_cache($url)
101
- {
102
- $parseUrl = parse_url($url);
103
- $pregex = '';
104
- // Default method is URLPURGE to purge only one object, this method is specific to cloudways configuration
105
- $purge_method = 'URLPURGE';
106
- // Use PURGE method when purging all site
107
- if (isset($parseUrl['query']) && ($parseUrl['query'] == 'breeze')) {
108
- // The regex is not needed as cloudways configuration purge all the cache of the domain when a PURGE is done
109
- $pregex = '.*';
110
- $purge_method = 'PURGE';
111
- }
112
- // Determine the path
113
- $path = '';
114
- if (isset($parseUrl['path'])) {
115
- $path = $parseUrl['path'];
116
- }
117
- // Determine the schema
118
- $schema = 'http://';
119
- if (isset($parseUrl['scheme'])) {
120
- $schema = $parseUrl['scheme'] . '://';
121
- }
122
- // Determine the host
123
- $host = $parseUrl['host'];
124
- $config = breeze_get_option( 'varnish_cache' );
125
- $varnish_host = isset($config['breeze-varnish-server-ip'])?$config['breeze-varnish-server-ip']:'127.0.0.1';
126
- $purgeme = $varnish_host . $path . $pregex;
127
- if (!empty($parseUrl['query']) && $parseUrl['query'] != 'breeze') {
128
- $purgeme .= '?' . $parseUrl['query'];
129
- }
130
- $request_args = array('method' => $purge_method, 'headers' => array('Host' => $host, 'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'), 'sslverify' => false);
131
- $response = wp_remote_request($schema . $purgeme, $request_args);
132
- if(is_wp_error($response) || $response['response']['code']!='200') {
133
- if($schema==='https://') {
134
- $schema = 'http://';
135
- }else{
136
- $schema = 'https://';
137
- }
138
- $response = wp_remote_request($schema . $purgeme, $request_args);
139
- }
140
- }
141
- //check permission
142
- public function check_permission()
143
- {
144
- return (!is_multisite() && current_user_can('activate_plugins')) || current_user_can('manage_network') || (is_multisite() && !current_user_can('manage_network') && (SUBDOMAIN_INSTALL || (!SUBDOMAIN_INSTALL && (BLOG_ID_CURRENT_SITE != $this->blogId))));
145
- }
146
- /*
147
- * Purge varnish cache with action if id post exists
148
- */
149
- public function purge_post($postId)
150
- {
151
- if ( 'save_post' === current_action() && did_action( 'edit_post' ) ) {
152
- // Prevent triggering this method twice when posts are updated.
153
- return;
154
- }
155
- $this->pushUrl($postId);
156
- }
157
- /*
158
- * Purge varnish cache after comment
159
- */
160
- public function purge_post_on_comment($comment_ID, $approved, $commentdata){
161
- if (empty($approved)) {
162
- return;
163
- }
164
- $postId = $commentdata['comment_post_ID'];
165
- $this->pushUrl($postId);
166
- }
167
- /*
168
- * if a comments status changes, purge varnish
169
- */
170
- public function purge_post_on_comment_status($comment_ID, $comment_status){
171
- $comment = get_comment($comment_ID);
172
- if(!empty($comment)){
173
- $postId = $comment->comment_post_ID;
174
- $this->pushUrl($postId);
175
- }
176
- }
177
- /*
178
- * Push url from post ID
179
- */
180
- public function pushUrl($postId){
181
- // If this is a valid post we want to purge the post,
182
- // the home page and any associated tags and categories
183
- $valid_post_status = array('publish', 'private', 'trash');
184
- $this_post_status = get_post_status($postId);
185
- // Not all post types are created equal
186
- $invalid_post_type = array('nav_menu_item', 'revision');
187
- $noarchive_post_type = array('post', 'page');
188
- $this_post_type = get_post_type($postId);
189
- // Determine the route for the rest API
190
- // This will need to be revisted if WP updates the version.
191
- $rest_api_route = 'wp/v2';
192
- // array to collect all our URLs
193
- $listofurls = array();
194
- // Verify we have a permalink and that we're a valid post status and a not an invalid post type
195
- if (get_permalink($postId) == true && in_array($this_post_status, $valid_post_status) && !in_array($this_post_type, $invalid_post_type)) {
196
- // Post URL
197
- array_push($listofurls, get_permalink($postId));
198
- // JSON API Permalink for the post based on type
199
- // We only want to do this if the rest_base exists
200
- $post_type_object = get_post_type_object($this_post_type);
201
- if (isset($post_type_object->rest_base) && !empty($post_type_object->rest_base)) {
202
- $rest_permalink = get_rest_url() . $rest_api_route . '/' . $post_type_object->rest_base . '/' . $postId . '/';
203
- } elseif ($this_post_type == 'post') {
204
- $rest_permalink = get_rest_url() . $rest_api_route . '/posts/' . $postId . '/';
205
- } elseif ($this_post_type == 'page') {
206
- $rest_permalink = get_rest_url() . $rest_api_route . '/views/' . $postId . '/';
207
- }
208
- if(isset($rest_permalink))
209
- array_push($listofurls, $rest_permalink);
210
- // Add in AMP permalink if Automattic's AMP is installed
211
- if (function_exists('amp_get_permalink')) {
212
- array_push($listofurls, amp_get_permalink($postId));
213
- }
214
- // Regular AMP url for posts
215
- array_push($listofurls, get_permalink($postId) . 'amp/');
216
- // Also clean URL for trashed post.
217
- if ($this_post_status == 'trash') {
218
- $trashpost = get_permalink($postId);
219
- $trashpost = str_replace('__trashed', '', $trashpost);
220
- array_push($listofurls, $trashpost, $trashpost . 'feed/');
221
- }
222
- // Category purge based on Donnacha's work in WP Super Cache
223
- $categories = get_the_category($postId);
224
- if ($categories) {
225
- foreach ($categories as $cat) {
226
- array_push($listofurls,
227
- get_category_link($cat->term_id),
228
- get_rest_url() . $rest_api_route . '/categories/' . $cat->term_id . '/'
229
- );
230
- }
231
- }
232
- // Tag purge based on Donnacha's work in WP Super Cache
233
- $tags = get_the_tags($postId);
234
- if ($tags) {
235
- foreach ($tags as $tag) {
236
- array_push($listofurls,
237
- get_tag_link($tag->term_id),
238
- get_rest_url() . $rest_api_route . '/tags/' . $tag->term_id . '/'
239
- );
240
- }
241
- }
242
- // Author URL
243
- $author_id = get_post_field('post_author', $postId);
244
- array_push($listofurls,
245
- get_author_posts_url($author_id),
246
- get_author_feed_link($author_id),
247
- get_rest_url() . $rest_api_route . '/users/' . $author_id . '/'
248
- );
249
- // Archives and their feeds
250
- if ($this_post_type && !in_array($this_post_type, $noarchive_post_type)) {
251
- array_push($listofurls,
252
- get_post_type_archive_link(get_post_type($postId)),
253
- get_post_type_archive_feed_link(get_post_type($postId))
254
- // Need to add in JSON?
255
- );
256
- }
257
- // Feeds
258
- array_push($listofurls,
259
- get_bloginfo_rss('rdf_url'),
260
- get_bloginfo_rss('rss_url'),
261
- get_bloginfo_rss('rss2_url'),
262
- get_bloginfo_rss('atom_url'),
263
- get_bloginfo_rss('comments_rss2_url'),
264
- get_post_comments_feed_link($postId)
265
- );
266
- // Home Pages and (if used) posts page
267
- array_push($listofurls,
268
- get_rest_url(),
269
- home_url() . '/'
270
- );
271
- if (get_option('show_on_front') == 'page') {
272
- // Ensure we have a page_for_posts setting to avoid empty URL
273
- if (get_option('page_for_posts')) {
274
- array_push($listofurls, get_permalink(get_option('page_for_posts')));
275
- }
276
- }
277
- } else {
278
- // Nothing
279
- return;
280
- }
281
- // Now flush all the URLs we've collected provided the array isn't empty
282
- if (!empty($listofurls)) {
283
- $this->urlsPurge = array_filter(
284
- array_unique(
285
- array_merge(
286
- $this->urlsPurge,
287
- $listofurls
288
- ),
289
- SORT_REGULAR
290
- )
291
- );
292
- }
293
- }
294
- }
295
- new Breeze_PurgeVarnish();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @copyright 2017 Cloudways https://www.cloudways.com
4
+ *
5
+ * Original development of this plugin by JoomUnited https://www.joomunited.com/
6
+ *
7
+ * This program is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation; either version 2 of the License, or
10
+ * (at your option) any later version.
11
+ *
12
+ * This program is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License
18
+ * along with this program; if not, write to the Free Software
19
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20
+ */
21
+ defined( 'ABSPATH' ) || die( 'No direct script access allowed!' );
22
+
23
+ class Breeze_PurgeVarnish {
24
+ protected $blogId;
25
+ protected $urlsPurge = array();
26
+ protected $auto_purge = false;
27
+ protected $actions = array(
28
+ 'switch_theme', // After a theme is changed
29
+ 'save_post', // Save a post
30
+ 'deleted_post', // Delete a post
31
+ 'edit_post', // Edit a post - includes leaving comments
32
+ );
33
+ protected $actionsNoId = array( 'switch_theme' );
34
+
35
+ public function __construct() {
36
+ global $blog_id;
37
+ $this->blogId = $blog_id;
38
+ $settings = breeze_get_option( 'varnish_cache' );
39
+ //storage config
40
+ if ( ! empty( $settings['auto-purge-varnish'] ) ) {
41
+ $this->auto_purge = (int) $settings['auto-purge-varnish'];
42
+ }
43
+ add_action( 'init', array( $this, 'init' ) );
44
+ }
45
+
46
+ public function init() {
47
+ //Push urlsPurge
48
+ if ( $this->auto_purge ) {
49
+ if ( ! empty( $this->actions ) ) {
50
+ //if enabled auto purge option , this action will start
51
+ foreach ( $this->actions as $action ) {
52
+ if ( in_array( $action, $this->actionsNoId ) ) {
53
+ add_action(
54
+ $action,
55
+ function () {
56
+ array_push( $this->urlsPurge, home_url() . '/?breeze' );
57
+ }
58
+ );
59
+ } else {
60
+ add_action( $action, array( $this, 'purge_post' ) );
61
+ }
62
+ }
63
+ }
64
+ //Pust urlsPurge after comment
65
+ add_action( 'comment_post', array( $this, 'purge_post_on_comment' ), 10, 3 );
66
+ add_action( 'wp_set_comment_status', array( $this, 'purge_post_on_comment_status' ), 10, 2 );
67
+ }
68
+ //Execute Purge
69
+ add_action( 'shutdown', array( $this, 'breeze_execute_purge' ) );
70
+ }
71
+
72
+ /**
73
+ * Execute Purge
74
+ *
75
+ */
76
+ public function breeze_execute_purge() {
77
+ $urlsPurge = array_unique( $this->urlsPurge );
78
+
79
+ if ( ! empty( $urlsPurge ) ) {
80
+ foreach ( $urlsPurge as $url ) {
81
+ $this->purge_cache( $url );
82
+ }
83
+ } else {
84
+ $homepage = home_url() . '/?breeze';
85
+ if ( isset( $_REQUEST['breeze_action'] ) && $_REQUEST['breeze_action'] == 'breeze_settings' ) {
86
+ if ( isset( $_POST['_breeze_nonce'] ) || wp_verify_nonce( $_POST['_breeze_nonce'], 'breeze_settings' ) ) {
87
+ do_action( 'breeze_clear_all_cache' );
88
+ }
89
+ }
90
+ if ( isset( $_GET['breeze_purge'] ) && check_admin_referer( 'breeze_purge_cache' ) ) {
91
+ //clear varnish cache
92
+ $admin = new Breeze_Admin();
93
+ $admin->breeze_clear_varnish();
94
+ //clear static cache
95
+ $size_cache = Breeze_Configuration::breeze_clean_cache();
96
+ if ( (int) $size_cache > 0 ) {
97
+ echo '<div id="message-clear-cache-top" style="margin: 10px 0px 10px 0;padding: 10px;" class="notice notice-success" ><strong>' . __( 'Cache data has been purged: ', 'breeze' ) . $size_cache . __( ' Kb static cache cleaned', 'breeze' ) . '</strong></div>';
98
+ } else {
99
+ echo '<div id="message-clear-cache-top" style="margin: 10px 0px 10px 0;padding: 10px;" class="notice notice-success" ><strong>' . __( 'Cache data has been purged.', 'breeze' ) . '</strong></div>';
100
+ }
101
+ }
102
+ }
103
+ }
104
+
105
+ /**
106
+ * Purge varnish cache
107
+ *
108
+ */
109
+ public function purge_cache( $url ) {
110
+ $parseUrl = parse_url( $url );
111
+ $pregex = '';
112
+ // Default method is URLPURGE to purge only one object, this method is specific to cloudways configuration
113
+ $purge_method = 'URLPURGE';
114
+ // Use PURGE method when purging all site
115
+ if ( isset( $parseUrl['query'] ) && ( $parseUrl['query'] == 'breeze' ) ) {
116
+ // The regex is not needed as cloudways configuration purge all the cache of the domain when a PURGE is done
117
+ $pregex = '.*';
118
+ $purge_method = 'PURGE';
119
+ }
120
+ // Determine the path
121
+ $path = '';
122
+ if ( isset( $parseUrl['path'] ) ) {
123
+ $path = $parseUrl['path'];
124
+ }
125
+ // Determine the schema
126
+ $schema = 'http://';
127
+ if ( isset( $parseUrl['scheme'] ) ) {
128
+ $schema = $parseUrl['scheme'] . '://';
129
+ }
130
+ // Determine the host
131
+ $host = $parseUrl['host'];
132
+ $config = breeze_get_option( 'varnish_cache' );
133
+ $varnish_host = isset( $config['breeze-varnish-server-ip'] ) ? $config['breeze-varnish-server-ip'] : '127.0.0.1';
134
+ $purgeme = $varnish_host . $path . $pregex;
135
+ if ( ! empty( $parseUrl['query'] ) && $parseUrl['query'] != 'breeze' ) {
136
+ $purgeme .= '?' . $parseUrl['query'];
137
+ }
138
+ $request_args = array(
139
+ 'method' => $purge_method,
140
+ 'headers' => array(
141
+ 'Host' => $host,
142
+ 'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36',
143
+ ),
144
+ 'sslverify' => false,
145
+ );
146
+ $response = wp_remote_request( $schema . $purgeme, $request_args );
147
+ if ( is_wp_error( $response ) || $response['response']['code'] != '200' ) {
148
+ if ( $schema === 'https://' ) {
149
+ $schema = 'http://';
150
+ } else {
151
+ $schema = 'https://';
152
+ }
153
+ $response = wp_remote_request( $schema . $purgeme, $request_args );
154
+ }
155
+ }
156
+
157
+ //check permission
158
+ public function check_permission() {
159
+ return ( ! is_multisite() && current_user_can( 'activate_plugins' ) ) || current_user_can( 'manage_network' ) || ( is_multisite() && ! current_user_can( 'manage_network' ) && ( SUBDOMAIN_INSTALL || ( ! SUBDOMAIN_INSTALL && ( BLOG_ID_CURRENT_SITE != $this->blogId ) ) ) );
160
+ }
161
+
162
+ /*
163
+ * Purge varnish cache with action if id post exists
164
+ */
165
+ public function purge_post( $postId ) {
166
+ if ( 'save_post' === current_action() && did_action( 'edit_post' ) ) {
167
+ // Prevent triggering this method twice when posts are updated.
168
+ return;
169
+ }
170
+ $this->pushUrl( $postId );
171
+ }
172
+
173
+ /*
174
+ * Purge varnish cache after comment
175
+ */
176
+ public function purge_post_on_comment( $comment_ID, $approved, $commentdata ) {
177
+ if ( empty( $approved ) ) {
178
+ return;
179
+ }
180
+ $postId = $commentdata['comment_post_ID'];
181
+ $this->pushUrl( $postId );
182
+ }
183
+
184
+ /*
185
+ * if a comments status changes, purge varnish
186
+ */
187
+ public function purge_post_on_comment_status( $comment_ID, $comment_status ) {
188
+ $comment = get_comment( $comment_ID );
189
+ if ( ! empty( $comment ) ) {
190
+ $postId = $comment->comment_post_ID;
191
+ $this->pushUrl( $postId );
192
+ }
193
+ }
194
+
195
+ /*
196
+ * Push url from post ID
197
+ */
198
+ public function pushUrl( $postId ) {
199
+ // If this is a valid post we want to purge the post,
200
+ // the home page and any associated tags and categories
201
+ $valid_post_status = array( 'publish', 'private', 'trash' );
202
+ $this_post_status = get_post_status( $postId );
203
+ // Not all post types are created equal
204
+ $invalid_post_type = array( 'nav_menu_item', 'revision' );
205
+ $noarchive_post_type = array( 'post', 'page' );
206
+ $this_post_type = get_post_type( $postId );
207
+ // Determine the route for the rest API
208
+ // This will need to be revisted if WP updates the version.
209
+ $rest_api_route = 'wp/v2';
210
+ // array to collect all our URLs
211
+ $listofurls = array();
212
+ // Verify we have a permalink and that we're a valid post status and a not an invalid post type
213
+ if ( get_permalink( $postId ) == true && in_array( $this_post_status, $valid_post_status ) && ! in_array( $this_post_type, $invalid_post_type ) ) {
214
+ // Post URL
215
+ array_push( $listofurls, get_permalink( $postId ) );
216
+ // JSON API Permalink for the post based on type
217
+ // We only want to do this if the rest_base exists
218
+ $post_type_object = get_post_type_object( $this_post_type );
219
+ if ( isset( $post_type_object->rest_base ) && ! empty( $post_type_object->rest_base ) ) {
220
+ $rest_permalink = get_rest_url() . $rest_api_route . '/' . $post_type_object->rest_base . '/' . $postId . '/';
221
+ } elseif ( $this_post_type == 'post' ) {
222
+ $rest_permalink = get_rest_url() . $rest_api_route . '/posts/' . $postId . '/';
223
+ } elseif ( $this_post_type == 'page' ) {
224
+ $rest_permalink = get_rest_url() . $rest_api_route . '/views/' . $postId . '/';
225
+ }
226
+ if ( isset( $rest_permalink ) ) {
227
+ array_push( $listofurls, $rest_permalink );
228
+ }
229
+ // Add in AMP permalink if Automattic's AMP is installed
230
+ if ( function_exists( 'amp_get_permalink' ) ) {
231
+ array_push( $listofurls, amp_get_permalink( $postId ) );
232
+ }
233
+ // Regular AMP url for posts
234
+ array_push( $listofurls, get_permalink( $postId ) . 'amp/' );
235
+ // Also clean URL for trashed post.
236
+ if ( $this_post_status == 'trash' ) {
237
+ $trashpost = get_permalink( $postId );
238
+ $trashpost = str_replace( '__trashed', '', $trashpost );
239
+ array_push( $listofurls, $trashpost, $trashpost . 'feed/' );
240
+ }
241
+ // Category purge based on Donnacha's work in WP Super Cache
242
+ $categories = get_the_category( $postId );
243
+ if ( $categories ) {
244
+ foreach ( $categories as $cat ) {
245
+ array_push(
246
+ $listofurls,
247
+ get_category_link( $cat->term_id ),
248
+ get_rest_url() . $rest_api_route . '/categories/' . $cat->term_id . '/'
249
+ );
250
+ }
251
+ }
252
+ // Tag purge based on Donnacha's work in WP Super Cache
253
+ $tags = get_the_tags( $postId );
254
+ if ( $tags ) {
255
+ foreach ( $tags as $tag ) {
256
+ array_push(
257
+ $listofurls,
258
+ get_tag_link( $tag->term_id ),
259
+ get_rest_url() . $rest_api_route . '/tags/' . $tag->term_id . '/'
260
+ );
261
+ }
262
+ }
263
+ // Author URL
264
+ $author_id = get_post_field( 'post_author', $postId );
265
+ array_push(
266
+ $listofurls,
267
+ get_author_posts_url( $author_id ),
268
+ get_author_feed_link( $author_id ),
269
+ get_rest_url() . $rest_api_route . '/users/' . $author_id . '/'
270
+ );
271
+ // Archives and their feeds
272
+ if ( $this_post_type && ! in_array( $this_post_type, $noarchive_post_type ) ) {
273
+ array_push(
274
+ $listofurls,
275
+ get_post_type_archive_link( get_post_type( $postId ) ),
276
+ get_post_type_archive_feed_link( get_post_type( $postId ) )
277
+ // Need to add in JSON?
278
+ );
279
+ }
280
+ // Feeds
281
+ array_push(
282
+ $listofurls,
283
+ get_bloginfo_rss( 'rdf_url' ),
284
+ get_bloginfo_rss( 'rss_url' ),
285
+ get_bloginfo_rss( 'rss2_url' ),
286
+ get_bloginfo_rss( 'atom_url' ),
287
+ get_bloginfo_rss( 'comments_rss2_url' ),
288
+ get_post_comments_feed_link( $postId )
289
+ );
290
+ // Home Pages and (if used) posts page
291
+ array_push(
292
+ $listofurls,
293
+ get_rest_url(),
294
+ home_url() . '/'
295
+ );
296
+ if ( get_option( 'show_on_front' ) == 'page' ) {
297
+ // Ensure we have a page_for_posts setting to avoid empty URL
298
+ if ( get_option( 'page_for_posts' ) ) {
299
+ array_push( $listofurls, get_permalink( get_option( 'page_for_posts' ) ) );
300
+ }
301
+ }
302
+ } else {
303
+ // Nothing
304
+ return;
305
+ }
306
+ // Now flush all the URLs we've collected provided the array isn't empty
307
+ if ( ! empty( $listofurls ) ) {
308
+ $this->urlsPurge = array_filter(
309
+ array_unique(
310
+ array_merge(
311
+ $this->urlsPurge,
312
+ $listofurls
313
+ ),
314
+ SORT_REGULAR
315
+ )
316
+ );
317
+ }
318
+ }
319
+ }
320
+
321
+ new Breeze_PurgeVarnish();
inc/helpers.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
  /**
3
- * @copyright 2017 Cloudways https://www.cloudways.com
4
  *
5
  * This program is free software; you can redistribute it and/or modify
6
  * it under the terms of the GNU General Public License as published by
@@ -22,7 +22,8 @@ defined( 'ABSPATH' ) || die( 'No direct script access allowed!' );
22
  * Retrieve site options accounting for settings inheritance.
23
  *
24
  * @param string $option_name
25
- * @param bool $is_local
 
26
  * @return array
27
  */
28
  function breeze_get_option( $option_name, $is_local = false ) {
@@ -53,8 +54,8 @@ function breeze_get_option( $option_name, $is_local = false ) {
53
  * Update site options accounting for multisite.
54
  *
55
  * @param string $option_name
56
- * @param mixed $value
57
- * @param bool $is_local
58
  */
59
  function breeze_update_option( $option_name, $value, $is_local = false ) {
60
  if ( is_network_admin() ) {
@@ -103,3 +104,300 @@ function breeze_is_supported( $check ) {
103
 
104
  return $return;
105
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <?php
2
  /**
3
+ * @copyright 2017 Cloudways https://www.cloudways.com
4
  *
5
  * This program is free software; you can redistribute it and/or modify
6
  * it under the terms of the GNU General Public License as published by
22
  * Retrieve site options accounting for settings inheritance.
23
  *
24
  * @param string $option_name
25
+ * @param bool $is_local
26
+ *
27
  * @return array
28
  */
29
  function breeze_get_option( $option_name, $is_local = false ) {
54
  * Update site options accounting for multisite.
55
  *
56
  * @param string $option_name
57
+ * @param mixed $value
58
+ * @param bool $is_local
59
  */
60
  function breeze_update_option( $option_name, $value, $is_local = false ) {
61
  if ( is_network_admin() ) {
104
 
105
  return $return;
106
  }
107
+
108
+ /**
109
+ * If an array provided, the function will check all
110
+ * array items to see if all of them are valid URLs.
111
+ *
112
+ * @param array $url_list
113
+ * @param string $extension
114
+ *
115
+ * @since 1.1.0
116
+ *
117
+ * @return bool
118
+ */
119
+ function breeze_validate_urls( $url_list = array() ) {
120
+ if ( ! is_array( $url_list ) ) {
121
+ return false;
122
+ }
123
+
124
+ $is_valid = true;
125
+ foreach ( $url_list as $url ) {
126
+ if ( ! filter_var( $url, FILTER_VALIDATE_URL ) ) {
127
+ $is_valid = false;
128
+ if ( false === $is_valid ) {
129
+ $is_valid = breeze_validate_url_via_regexp( $url );
130
+ }
131
+ }
132
+
133
+ if ( false === $is_valid ) {
134
+ break;
135
+ }
136
+ }
137
+
138
+ return $is_valid;
139
+
140
+ }
141
+
142
+ function breeze_validate_the_right_extension( $url_list = array(), $extension = 'css' ) {
143
+ if ( ! is_array( $url_list ) ) {
144
+ return false;
145
+ }
146
+
147
+ $is_valid = true;
148
+ foreach ( $url_list as $url ) {
149
+
150
+ $is_regexp = breeze_string_contains_exclude_regexp( $url );
151
+
152
+ if ( false === $is_regexp ) {
153
+ $is_valid = breeze_validate_exclude_field_by_extension( $url, $extension );
154
+ } else {
155
+ $file_extension = breeze_get_file_extension_from_url( $url );
156
+
157
+ if ( false !== $file_extension && strtolower( $extension ) !== $file_extension ) {
158
+ $is_valid = false;
159
+ }
160
+ }
161
+
162
+ if ( false === $is_valid ) {
163
+ break;
164
+ }
165
+ }
166
+
167
+ return $is_valid;
168
+ }
169
+
170
+ /**
171
+ * Returns the extension for given file from url.
172
+ *
173
+ * @param string $url_given
174
+ *
175
+ * @return bool
176
+ */
177
+ function breeze_get_file_extension_from_url( $url_given = '' ) {
178
+ if ( empty( $url_given ) ) {
179
+ return false;
180
+ }
181
+
182
+ $file_path = wp_parse_url( $url_given, PHP_URL_PATH );
183
+ if ( ! empty( $file_path ) ) {
184
+ $file_name = wp_basename( $file_path );
185
+ if ( ! empty( $file_name ) ) {
186
+ $bits = explode( '.', $file_name );
187
+ if ( ! empty( $bits ) ) {
188
+ $extension_id = count( $bits ) - 1;
189
+ $extension = strtolower( $bits[ $extension_id ] );
190
+ $extension = preg_replace( '/\s+/', ' ', $extension );
191
+ if ( '*)' === $extension ) { // Exception when (.*) is the last statement instead of ending with an extension
192
+ return false;
193
+ }
194
+
195
+ return $extension;
196
+ }
197
+ }
198
+ }
199
+
200
+ return false;
201
+ }
202
+
203
+ /**
204
+ * Will search for given string in array values
205
+ * if found, will result in an array with all entries found
206
+ * if not found, an empty array will be resulted.
207
+ *
208
+ * @since 1.1.0
209
+ *
210
+ * @param string $needle
211
+ * @param array $haystack
212
+ *
213
+ * @return array
214
+ */
215
+ function breeze_is_string_in_array_values( $needle = '', $haystack = array() ) {
216
+ if ( empty( $needle ) || empty( $haystack ) ) {
217
+ return array();
218
+ }
219
+ $needle = trim( $needle );
220
+ $is_string_in_array = array_filter(
221
+ $haystack,
222
+ function ( $var ) use ( $needle ) {
223
+ #return false;
224
+ if ( breeze_string_contains_exclude_regexp( $var ) ) {
225
+ return breeze_file_match_pattern( $needle, $var );
226
+ } else {
227
+ return strpos( $var, $needle ) !== false;
228
+ }
229
+
230
+ }
231
+ );
232
+
233
+ return $is_string_in_array;
234
+ }
235
+
236
+ /**
237
+ * Will return true for Google fonts and other type of CDN link
238
+ * that are missing the Scheme from the url
239
+ *
240
+ *
241
+ * @param string $url_to_be_checked
242
+ *
243
+ * @return bool
244
+ */
245
+ function breeze_validate_url_via_regexp( $url_to_be_checked = '' ) {
246
+ if ( empty( $url_to_be_checked ) ) {
247
+ return false;
248
+ }
249
+ $regex = '((http:|https:?)?\/\/)?([a-z0-9+!*(),;?&=.-]+(:[a-z0-9+!*(),;?&=.-]+)?@)?([a-z0-9\-\.]*)\.(([a-z]{2,4})|([0-9]{1,3}\.([0-9]{1,3})\.([0-9]{1,3})))(:[0-9]{2,5})?(\/([a-z0-9+%-]\.?)+)*\/?(\?[a-z+&$_.-][a-z0-9;:@&%=+/.-/,/:]*)?(#[a-z_.-][a-z0-9+$%_.-]*)?';
250
+
251
+ preg_match( "~^$regex$~i", $url_to_be_checked, $matches_found );
252
+
253
+ if ( empty( $matches_found ) ) {
254
+ return false;
255
+ }
256
+
257
+ return true;
258
+ }
259
+
260
+
261
+ /**
262
+ * Used in Breeze settings to validate if the URL corresponds to the
263
+ * added input/textarea
264
+ * Exclude CSS must contain only .css files
265
+ * Exclude JS must contain only .js files
266
+ *
267
+ * @param $file_url
268
+ * @param string $validate
269
+ *
270
+ * @return bool
271
+ */
272
+ function breeze_validate_exclude_field_by_extension( $file_url, $validate = 'css' ) {
273
+ if ( empty( $file_url ) ) {
274
+ return true;
275
+ }
276
+ if ( empty( $validate ) ) {
277
+ return false;
278
+ }
279
+
280
+ $valid = true;
281
+ $file_path = wp_parse_url( $file_url, PHP_URL_PATH );
282
+ $preg_match = preg_match( '#\.' . $validate . '$#', $file_path );
283
+ if ( empty( $preg_match ) ) {
284
+ $valid = false;
285
+ }
286
+
287
+ return $valid;
288
+
289
+ }
290
+
291
+
292
+ /**
293
+ * Function used to determine if the excluded URL contains regexp
294
+ *
295
+ * @param $file_url
296
+ * @param string $validate
297
+ *
298
+ * @return bool
299
+ */
300
+ function breeze_string_contains_exclude_regexp( $file_url, $validate = '(.*)' ) {
301
+ if ( empty( $file_url ) ) {
302
+ return false;
303
+ }
304
+ if ( empty( $validate ) ) {
305
+ return false;
306
+ }
307
+
308
+ $valid = false;
309
+
310
+ if ( strpos( $file_url, $validate ) !== false ) {
311
+ $valid = true; // 0 or false
312
+ }
313
+
314
+ return $valid;
315
+ }
316
+
317
+ /**
318
+ * Method will prepare the URLs escaped for preg_match
319
+ * Will return the file_url matches the pattern.
320
+ * empty array for false,
321
+ * aray with data for true.
322
+ *
323
+ * @param $file_url
324
+ * @param $pattern
325
+ *
326
+ * @return false|int
327
+ */
328
+ function breeze_file_match_pattern( $file_url, $pattern ) {
329
+ $remove_pattern = str_replace( '(.*)', 'REG_EXP_ALL', $pattern );
330
+ $prepared_pattern = preg_quote( $remove_pattern, '/' );
331
+ $pattern = str_replace( 'REG_EXP_ALL', '(.*)', $prepared_pattern );
332
+ $result = preg_match( '/' . $pattern . '/', $file_url );
333
+
334
+ return $result;
335
+ }
336
+
337
+
338
+ /**
339
+ * Will return true/false if the cache headers exist and
340
+ * have values HIT or MISS.
341
+ * HIT = Varnish is enabled and age is cached
342
+ * MISS = Varnish is disabled or the cache has been purged.
343
+ * This method will request only the current url homepage headers
344
+ * and if the first time is a MISS, it will try again.
345
+ *
346
+ * @param int $retry
347
+ *
348
+ * @return bool
349
+ */
350
+ function is_varnish_cache_started( $retry = 1 ) {
351
+ // Making sure the request is only for HEADER info without getting the content from the page
352
+ $context_options = array(
353
+ 'http' => array(
354
+ 'method' => 'HEAD',
355
+ 'follow_location' => 1,
356
+ ),
357
+ 'ssl' => array(
358
+ 'verify_peer' => false
359
+ ),
360
+ );
361
+ $context = stream_context_create( $context_options );
362
+
363
+ $url_ping = trim( home_url() . '?breeze_check_cache_available=' . time() );
364
+ $headers = get_headers( $url_ping, 1, $context );
365
+
366
+ if ( empty( $headers ) ) {
367
+ return false;
368
+ }
369
+
370
+ $headers = array_change_key_case( $headers, CASE_LOWER );
371
+
372
+ if ( ! isset( $headers['x-cache'] ) ) {
373
+ if ( 1 === $retry ) {
374
+ $retry ++;
375
+
376
+ return is_varnish_cache_started( $retry );
377
+ }
378
+
379
+ return false;
380
+ } else {
381
+ $cache_header = strtolower( trim( $headers['x-cache'] ) );
382
+
383
+ // After the cache is cleared, the first time the headers will say that the cache is not used
384
+ // After the first header requests, the cache headers are formed.
385
+ // Checking the second time will give better results.
386
+ if ( 1 === $retry ) {
387
+ if ( 'hit' === $cache_header ) {
388
+ return true;
389
+ } else {
390
+ $retry ++;
391
+
392
+ return is_varnish_cache_started( $retry );
393
+ }
394
+ } else {
395
+
396
+ if ( 'hit' === $cache_header ) {
397
+ return true;
398
+ }
399
+
400
+ return false;
401
+ }
402
+ }
403
+ }
inc/minification/breeze-minification-scripts.php CHANGED
@@ -168,10 +168,12 @@ class Breeze_MinificationScripts extends Breeze_MinificationBase {
168
  $url = substr($url, 0 , -1);
169
  }
170
 
 
 
171
  //exclude js
172
- if(in_array($url,$this->custom_js_exclude)){
173
- continue;
174
- }
175
 
176
  $path = $this->getpath($url);
177
  if($path !== false && preg_match('#\.js$#',$path)) {
168
  $url = substr($url, 0 , -1);
169
  }
170
 
171
+ // Let's check if this file is in the excluded list.
172
+ $is_excluded = breeze_is_string_in_array_values( $url, $this->custom_js_exclude );
173
  //exclude js
174
+ if ( ! empty( $is_excluded ) ) {
175
+ continue;
176
+ }
177
 
178
  $path = $this->getpath($url);
179
  if($path !== false && preg_match('#\.js$#',$path)) {
inc/minification/breeze-minification-styles.php CHANGED
@@ -2,7 +2,9 @@
2
  /*
3
  * Based on some work of autoptimize plugin
4
  */
5
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
 
 
6
  class Breeze_MinificationStyles extends Breeze_MinificationBase {
7
  private $css = array();
8
  private $csscode = array();
@@ -20,55 +22,58 @@ class Breeze_MinificationStyles extends Breeze_MinificationBase {
20
  private $cssremovables = array();
21
  private $include_inline = false;
22
  private $inject_min_late = '';
23
- private $group_css = false;
24
- private $custom_css_exclude = array();
25
- private $css_group_val = array();
26
- private $css_min_arr = array();
27
- private $issetminfile = false;
28
- private $url_group_arr = array();
 
29
  //Reads the page and collects style tags
30
- public function read($options) {
31
  $noptimizeCSS = apply_filters( 'breeze_filter_css_noptimize', false, $this->content );
32
- if ($noptimizeCSS) return false;
 
 
33
  $whitelistCSS = apply_filters( 'breeze_filter_css_whitelist', '' );
34
- if (!empty($whitelistCSS)) {
35
- $this->whitelist = array_filter(array_map('trim',explode(",",$whitelistCSS)));
36
  }
37
- if ($options['nogooglefont'] == true) {
38
  $removableCSS = "fonts.googleapis.com";
39
  } else {
40
  $removableCSS = "";
41
  }
42
- $removableCSS = apply_filters( 'breeze_filter_css_removables', $removableCSS);
43
- if (!empty($removableCSS)) {
44
- $this->cssremovables = array_filter(array_map('trim',explode(",",$removableCSS)));
45
  }
46
- $this->cssinlinesize = apply_filters('breeze_filter_css_inlinesize',256);
47
  // filter to "late inject minified CSS", default to true for now (it is faster)
48
- $this->inject_min_late = apply_filters('breeze_filter_css_inject_min_late',true);
49
  // Remove everything that's not the header
50
- if ( apply_filters('breeze_filter_css_justhead',$options['justhead']) == true ) {
51
- $content = explode('</head>',$this->content,2);
52
- $this->content = $content[0].'</head>';
53
  $this->restofcontent = $content[1];
54
  }
55
  // include inline?
56
- if( apply_filters('breeze_css_include_inline',$options['include_inline']) == true ) {
57
  $this->include_inline = true;
58
  }
59
- // group css?
60
- if( apply_filters('breeze_css_include_inline',$options['groupcss']) == true ) {
61
- $this->group_css = true;
62
- }
63
- //custom js exclude
64
- if(!empty($options['custom_css_exclude'])){
65
- $this->custom_css_exclude = $options['custom_css_exclude'];
66
- }
67
  // what CSS shouldn't be autoptimized
68
  $excludeCSS = $options['css_exclude'];
69
  $excludeCSS = apply_filters( 'breeze_filter_css_exclude', $excludeCSS );
70
- if ($excludeCSS!=="") {
71
- $this->dontmove = array_filter(array_map('trim',explode(",",$excludeCSS)));
72
  } else {
73
  $this->dontmove = "";
74
  }
@@ -88,628 +93,648 @@ class Breeze_MinificationStyles extends Breeze_MinificationBase {
88
  // Store data: URIs setting for later use
89
  $this->datauris = $options['datauris'];
90
  // noptimize me
91
- $this->content = $this->hide_noptimize($this->content);
92
  // exclude (no)script, as those may contain CSS which should be left as is
93
- if ( strpos( $this->content, '<script' ) !== false ) {
94
  $this->content = preg_replace_callback(
95
  '#<(?:no)?script.*?<\/(?:no)?script>#is',
96
- function($matches){
97
- return "%%SCRIPT".breeze_HASH."%%".base64_encode($matches[0])."%%SCRIPT%%";
98
- },
99
  $this->content
100
  );
101
  }
102
  // Save IE hacks
103
- $this->content = $this->hide_iehacks($this->content);
104
  // hide comments
105
- $this->content = $this->hide_comments($this->content);
106
  // Get <style> and <link>
107
- if(preg_match_all('#(<style[^>]*>.*</style>)|(<link[^>]*stylesheet[^>]*>)#Usmi',$this->content,$matches)) {
108
- foreach($matches[0] as $tag) {
109
- if ($this->isremovable($tag,$this->cssremovables)) {
110
- $this->content = str_replace($tag,'',$this->content);
111
- } else if ($this->ismovable($tag)) {
112
  // Get the media
113
- if(strpos($tag,'media=')!==false) {
114
- preg_match('#media=(?:"|\')([^>]*)(?:"|\')#Ui',$tag,$medias);
115
- $medias = explode(',',$medias[1]);
116
- $media = array();
117
- foreach($medias as $elem) {
118
- if (empty($elem)) { $elem="all"; }
 
 
119
  $media[] = $elem;
120
  }
121
  } else {
122
  // No media specified - applies to all
123
- $media = array('all');
124
  }
125
- $media = apply_filters( 'breeze_filter_css_tagmedia',$media,$tag );
126
- if(preg_match('#<link.*href=("|\')(.*)("|\')#Usmi',$tag,$source)) {
127
  // <link>
128
- $url = current(explode('?',$source[2],2));
129
- //exclude css file
130
- if(in_array($url,$this->custom_css_exclude)){
131
- continue;
132
- }
133
- $path = $this->getpath($url);
134
- if($path!==false && preg_match('#\.css$#',$path)) {
 
 
135
  // Good link
136
- $this->css[] = array($media,$path);
137
- }else{
138
  // Link is dynamic (.php etc)
139
  $tag = '';
140
  }
141
  } else {
142
  // inline css in style tags can be wrapped in comment tags, so restore comments
143
- $tag = $this->restore_comments($tag);
144
- preg_match('#<style.*>(.*)</style>#Usmi',$tag,$code);
145
  // and re-hide them to be able to to the removal based on tag
146
- $tag = $this->hide_comments($tag);
147
  if ( $this->include_inline ) {
148
- $code = preg_replace('#^.*<!\[CDATA\[(?:\s*\*/)?(.*)(?://|/\*)\s*?\]\]>.*$#sm','$1',$code[1]);
149
- $this->css[] = array($media,'INLINE;'.$code);
150
  } else {
151
  $tag = '';
152
  }
153
  }
154
  // Remove the original style tag
155
- $this->content = str_replace($tag,'',$this->content);
156
  }
157
  }
 
158
  return true;
159
  }
 
160
  // Really, no styles?
161
  return false;
162
  }
 
163
  // Joins and optimizes CSS
164
  public function minify() {
165
- foreach($this->css as $group) {
166
- list($media,$css) = $group;
167
- if(preg_match('#^INLINE;#',$css)) {
168
  // <style>
169
- $css = preg_replace('#^INLINE;#','',$css);
170
- $css = $this->fixurls(ABSPATH.'/index.php',$css);
171
  $tmpstyle = apply_filters( 'breeze_css_individual_style', $css, "" );
172
- if ( has_filter('breeze_css_individual_style') && !empty($tmpstyle) ) {
173
- $css=$tmpstyle;
174
- $this->alreadyminified=true;
175
  }
176
  } else {
177
  //<link>
178
- if($css !== false && file_exists($css) && is_readable($css)) {
179
- $cssPath = $css;
180
- $css = $this->fixurls($cssPath,file_get_contents($cssPath));
181
- $css = preg_replace('/\x{EF}\x{BB}\x{BF}/','',$css);
182
  $tmpstyle = apply_filters( 'breeze_css_individual_style', $css, $cssPath );
183
- if (has_filter('breeze_css_individual_style') && !empty($tmpstyle)) {
184
- $css=$tmpstyle;
185
- $this->alreadyminified=true;
186
- } else if ($this->can_inject_late($cssPath,$css)) {
187
- $css="%%INJECTLATER".breeze_HASH."%%".base64_encode($cssPath)."|".md5($css)."%%INJECTLATER%%";
188
  }
189
  } else {
190
  // Couldn't read CSS. Maybe getpath isn't working?
191
  $css = '';
192
  }
193
  }
194
- if($this->group_css == true){
195
- foreach($media as $elem) {
196
- if(!isset($this->csscode[$elem]))
197
- $this->csscode[$elem] = '';
198
- $this->csscode[$elem] .= "\n/*FILESTART*/".$css;
199
- }
200
- }else{
201
- foreach ($media as $elem){
202
- $this->css_group_val[] = $elem."_breezecssgroup_".$css;
203
- }
204
- }
205
- }
206
- if($this->group_css == true){
207
- // Check for duplicate code
208
- $md5list = array();
209
- $tmpcss = $this->csscode;
210
- foreach($tmpcss as $media => $code) {
211
- $md5sum = md5($code);
212
- $medianame = $media;
213
- foreach($md5list as $med => $sum) {
214
- // If same code
215
- if($sum === $md5sum) {
216
- //Add the merged code
217
- $medianame = $med.', '.$media;
218
- $this->csscode[$medianame] = $code;
219
- $md5list[$medianame] = $md5list[$med];
220
- unset($this->csscode[$med], $this->csscode[$media]);
221
- unset($md5list[$med]);
222
- }
223
- }
224
- $md5list[$medianame] = $md5sum;
225
- }
226
- unset($tmpcss);
227
- // Manage @imports, while is for recursive import management
228
- foreach ($this->csscode as &$thiscss) {
229
- // Flag to trigger import reconstitution and var to hold external imports
230
- $fiximports = false;
231
- $external_imports = "";
232
- while(preg_match_all('#^(/*\s?)@import.*(?:;|$)#Um',$thiscss,$matches)) {
233
- foreach($matches[0] as $import) {
234
- if ($this->isremovable($import,$this->cssremovables)) {
235
- $thiscss = str_replace($import,'',$thiscss);
236
- $import_ok = true;
237
- } else {
238
- $url = trim(preg_replace('#^.*((?:https?:|ftp:)?//.*\.css).*$#','$1',trim($import))," \t\n\r\0\x0B\"'");
239
- $path = $this->getpath($url);
240
- $import_ok = false;
241
- if (file_exists($path) && is_readable($path)) {
242
- $code = addcslashes($this->fixurls($path,file_get_contents($path)),"\\");
243
- $code = preg_replace('/\x{EF}\x{BB}\x{BF}/','',$code);
244
- $tmpstyle = apply_filters( 'breeze_css_individual_style', $code, "" );
245
- if ( has_filter('breeze_css_individual_style') && !empty($tmpstyle)) {
246
- $code=$tmpstyle;
247
- $this->alreadyminified=true;
248
- } else if ($this->can_inject_late($path,$code)) {
249
- $code="%%INJECTLATER".breeze_HASH."%%".base64_encode($path)."|".md5($code)."%%INJECTLATER%%";
250
- }
251
- if(!empty($code)) {
252
- $tmp_thiscss = preg_replace('#(/\*FILESTART\*/.*)'.preg_quote($import,'#').'#Us','/*FILESTART2*/'.$code.'$1',$thiscss);
253
- if (!empty($tmp_thiscss)) {
254
- $thiscss = $tmp_thiscss;
255
- $import_ok = true;
256
- unset($tmp_thiscss);
257
- }
258
- unset($code);
259
- }
260
- }
261
- }
262
- if (!$import_ok) {
263
- // external imports and general fall-back
264
- $external_imports .= $import;
265
- $thiscss = str_replace($import,'',$thiscss);
266
- $fiximports = true;
267
- }
268
- }
269
- $thiscss = preg_replace('#/\*FILESTART\*/#','',$thiscss);
270
- $thiscss = preg_replace('#/\*FILESTART2\*/#','/*FILESTART*/',$thiscss);
271
- }
272
- // add external imports to top of aggregated CSS
273
- if($fiximports) {
274
- $thiscss=$external_imports.$thiscss;
275
- }
276
- }
277
- unset($thiscss);
278
- // $this->csscode has all the uncompressed code now.
279
- $mhtmlcount = 0;
280
- foreach($this->csscode as &$code) {
281
- // Check for already-minified code
282
- $hash = md5($code);
283
- $ccheck = new Breeze_MinificationCache($hash,'css');
284
- if($ccheck->check()) {
285
- $code = $ccheck->retrieve();
286
- $this->hashmap[md5($code)] = $hash;
287
- continue;
288
- }
289
- unset($ccheck);
290
- // Do the imaging!
291
- $imgreplace = array();
292
- preg_match_all('#(background[^;}]*url\((?!\s?"?\s?data)(.*)\)[^;}]*)(?:;|$|})#Usm',$code,$matches);
293
- if(($this->datauris == true) && (function_exists('base64_encode')) && (is_array($matches))) {
294
- foreach($matches[2] as $count => $quotedurl) {
295
- $iurl = trim($quotedurl," \t\n\r\0\x0B\"'");
296
- // if querystring, remove it from url
297
- if (strpos($iurl,'?') !== false) { $iurl = strtok($iurl,'?'); }
298
- $ipath = $this->getpath($iurl);
299
- $datauri_max_size = 4096;
300
- $datauri_max_size = (int) apply_filters( 'breeze_filter_css_datauri_maxsize', $datauri_max_size );
301
- $datauri_exclude = apply_filters( 'breeze_filter_css_datauri_exclude', "");
302
- if (!empty($datauri_exclude)) {
303
- $no_datauris=array_filter(array_map('trim',explode(",",$datauri_exclude)));
304
- foreach ($no_datauris as $no_datauri) {
305
- if (strpos($iurl,$no_datauri)!==false) {
306
- $ipath=false;
307
- break;
308
- }
309
- }
310
- }
311
- if($ipath != false && preg_match('#\.(jpe?g|png|gif|bmp)$#i',$ipath) && file_exists($ipath) && is_readable($ipath) && filesize($ipath) <= $datauri_max_size) {
312
- $ihash=md5($ipath);
313
- $icheck = new Breeze_MinificationCache($ihash,'img');
314
- if($icheck->check()) {
315
- // we have the base64 image in cache
316
- $headAndData=$icheck->retrieve();
317
- $_base64data=explode(";base64,",$headAndData);
318
- $base64data=$_base64data[1];
319
- } else {
320
- // It's an image and we don't have it in cache, get the type
321
- $explA=explode('.',$ipath);
322
- $type=end($explA);
323
- switch($type) {
324
- case 'jpeg':
325
- $dataurihead = 'data:image/jpeg;base64,';
326
- break;
327
- case 'jpg':
328
- $dataurihead = 'data:image/jpeg;base64,';
329
- break;
330
- case 'gif':
331
- $dataurihead = 'data:image/gif;base64,';
332
- break;
333
- case 'png':
334
- $dataurihead = 'data:image/png;base64,';
335
- break;
336
- case 'bmp':
337
- $dataurihead = 'data:image/bmp;base64,';
338
- break;
339
- default:
340
- $dataurihead = 'data:application/octet-stream;base64,';
341
- }
342
- // Encode the data
343
- $base64data = base64_encode(file_get_contents($ipath));
344
- $headAndData=$dataurihead.$base64data;
345
- // Save in cache
346
- $icheck->cache($headAndData,"text/plain");
347
- }
348
- unset($icheck);
349
- // Add it to the list for replacement
350
- $imgreplace[$matches[1][$count]] = str_replace($quotedurl,$headAndData,$matches[1][$count]).";\n*".str_replace($quotedurl,'mhtml:%%MHTML%%!'.$mhtmlcount,$matches[1][$count]).";\n_".$matches[1][$count].';';
351
- // Store image on the mhtml document
352
- $this->mhtml .= "--_\r\nContent-Location:{$mhtmlcount}\r\nContent-Transfer-Encoding:base64\r\n\r\n{$base64data}\r\n";
353
- $mhtmlcount++;
354
- } else {
355
- // just cdn the URL if applicable
356
- if (!empty($this->cdn_url)) {
357
- $url = trim($quotedurl," \t\n\r\0\x0B\"'");
358
- $cdn_url=$this->url_replace_cdn($url);
359
- $imgreplace[$matches[1][$count]] = str_replace($quotedurl,$cdn_url,$matches[1][$count]);
360
- }
361
- }
362
- }
363
- } else if ((is_array($matches)) && (!empty($this->cdn_url))) {
364
- // change background image urls to cdn-url
365
- foreach($matches[2] as $count => $quotedurl) {
366
- $url = trim($quotedurl," \t\n\r\0\x0B\"'");
367
- $cdn_url=$this->url_replace_cdn($url);
368
- $imgreplace[$matches[1][$count]] = str_replace($quotedurl,$cdn_url,$matches[1][$count]);
369
- }
370
- }
371
- if(!empty($imgreplace)) {
372
- $code = str_replace(array_keys($imgreplace),array_values($imgreplace),$code);
373
- }
374
- // CDN the fonts!
375
- if ( (!empty($this->cdn_url)) && (apply_filters('breeze_filter_css_fonts_cdn',false)) && (version_compare(PHP_VERSION, '5.3.0') >= 0) ) {
376
- $fontreplace = array();
377
- include_once(BREEZE_PLUGIN_DIR.'inc/minification/config/minificationFontRegex.php');
378
- preg_match_all($fonturl_regex,$code,$matches);
379
- if (is_array($matches)) {
380
- foreach($matches[8] as $count => $quotedurl) {
381
- $url = trim($quotedurl," \t\n\r\0\x0B\"'");
382
- $cdn_url=$this->url_replace_cdn($url);
383
- $fontreplace[$matches[8][$count]] = str_replace($quotedurl,$cdn_url,$matches[8][$count]);
384
- }
385
- if(!empty($fontreplace)) {
386
- $code = str_replace(array_keys($fontreplace),array_values($fontreplace),$code);
387
- }
388
- }
389
- }
390
- // Minify
391
- if (($this->alreadyminified!==true) && (apply_filters( "breeze_css_do_minify", true))) {
392
- if (class_exists('Minify_CSS_Compressor')) {
393
- $tmp_code = trim(Minify_CSS_Compressor::process($code));
394
- } else if(class_exists('CSSmin')) {
395
- $cssmin = new CSSmin();
396
- if (method_exists($cssmin,"run")) {
397
- $tmp_code = trim($cssmin->run($code));
398
- } elseif (@is_callable(array($cssmin,"minify"))) {
399
- $tmp_code = trim(CssMin::minify($code));
400
- }
401
- }
402
- if (!empty($tmp_code)) {
403
- $code = $tmp_code;
404
- unset($tmp_code);
405
- }
406
- }
407
- $code = $this->inject_minified($code);
408
- $tmp_code = apply_filters( 'breeze_css_after_minify',$code );
409
- if (!empty($tmp_code)) {
410
- $code = $tmp_code;
411
- unset($tmp_code);
412
- }
413
- $this->hashmap[md5($code)] = $hash;
414
- }
415
- unset($code);
416
- }else{
417
- foreach ($this->css_group_val as $value){
418
- $media = substr($value, 0 , strpos($value,'_breezecssgroup_'));
419
- $css = substr($value,strpos($value,'_breezecssgroup_')+strlen('_breezecssgroup_'));
420
- $hash = md5($css);
421
- $ccheck = new Breeze_MinificationCache($hash,'css');
422
- if($ccheck->check()) {
423
- $css_exist = $ccheck->retrieve();
424
- $this->css_min_arr[] = $media."_breezemedia_".$hash."_breezekey_".$css_exist;
425
- continue;
426
- }
427
- unset($ccheck);
428
- // Minify
429
- if (class_exists('Minify_CSS_Compressor')) {
430
- $tmp_code = trim(Minify_CSS_Compressor::process($css));
431
- } else if(class_exists('CSSmin')) {
432
- $cssmin = new CSSmin();
433
- if (method_exists($cssmin,"run")) {
434
- $tmp_code = trim($cssmin->run($css));
435
- } elseif (@is_callable(array($cssmin,"minify"))) {
436
- $tmp_code = trim(CssMin::minify($css));
437
- }
438
- }
439
- if (!empty($tmp_code)) {
440
- $css = $tmp_code;
441
- unset($tmp_code);
442
- }
443
- $css = $this->inject_minified($css);
444
- $css = apply_filters( 'breeze_css_after_minify',$css );
445
- $this->css_min_arr[] = $media."_breezemedia_".$hash."_breezekey_".$css;
446
- }
447
- unset($css);
448
- }
 
 
 
 
449
  return true;
450
  }
 
451
  //Caches the CSS in uncompressed, deflated and gzipped form.
452
  public function cache() {
453
- if($this->datauris) {
454
  // MHTML Preparation
455
- $this->mhtml = "/*\r\nContent-Type: multipart/related; boundary=\"_\"\r\n\r\n".$this->mhtml."*/\r\n";
456
- $md5 = md5($this->mhtml);
457
- $cache = new Breeze_MinificationCache($md5,'txt');
458
- if(!$cache->check()) {
459
  // Cache our images for IE
460
- $cache->cache($this->mhtml,'text/plain');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
461
  }
462
- $mhtml = breeze_CACHE_URL.$cache->getname();
463
  }
464
- if($this->group_css == true){
465
- // CSS cache
466
- foreach($this->csscode as $media => $code) {
467
- $md5 = $this->hashmap[md5($code)];
468
- if($this->datauris) {
469
- // Images for ie! Get the right url
470
- $code = str_replace('%%MHTML%%',$mhtml,$code);
471
- }
472
- $cache = new Breeze_MinificationCache($md5,'css');
473
- if(!$cache->check()) {
474
- // Cache our code
475
- $cache->cache($code,'text/css');
476
- }
477
- $this->url[$media] = breeze_CACHE_URL.$cache->getname();
478
- }
479
- }else{
480
- foreach ($this->css_min_arr as $value){
481
- $media = substr($value,0,strpos($value,'_breezemedia_'));
482
- $code = substr($value,strpos($value,'_breezemedia_')+strlen('_breezemedia_'));
483
- $hash = substr($code,0,strpos($code,'_breezekey_'));
484
- $css = substr($code,strpos($code,'_breezekey_')+strlen('_breezekey_'));
485
- $cache = new Breeze_MinificationCache($hash,'css');
486
- if(!$cache->check()) {
487
- // Cache our code
488
- $cache->cache($css,'text/css');
489
- }
490
- $this->url_group_arr[] = $media."_breezemedia_".$hash."_breezekey_".breeze_CACHE_URL.$cache->getname();
491
- }
492
- }
493
  }
 
494
  //Returns the content
495
  public function getcontent() {
496
  // restore IE hacks
497
- $this->content = $this->restore_iehacks($this->content);
498
  // restore comments
499
- $this->content = $this->restore_comments($this->content);
500
  // restore (no)script
501
- if ( strpos( $this->content, '%%SCRIPT%%' ) !== false ) {
502
  $this->content = preg_replace_callback(
503
- '#%%SCRIPT'.breeze_HASH.'%%(.*?)%%SCRIPT%%#is',
504
 
505
- function ($matches){
506
- return base64_decode($matches[1]);
507
- },
508
  $this->content
509
  );
510
  }
511
  // restore noptimize
512
- $this->content = $this->restore_noptimize($this->content);
513
  //Restore the full content
514
- if(!empty($this->restofcontent)) {
515
- $this->content .= $this->restofcontent;
516
  $this->restofcontent = '';
517
  }
518
  // Inject the new stylesheets
519
- $replaceTag = array("<title","before");
520
  $replaceTag = apply_filters( 'breeze_filter_css_replacetag', $replaceTag );
521
- if($this->group_css == true){
522
- if ($this->inline == true) {
523
- foreach($this->csscode as $media => $code) {
524
- $this->inject_in_html('<style type="text/css" media="'.$media.'">'.$code.'</style>',$replaceTag);
525
- }
526
- } else {
527
- if ($this->defer == true) {
528
- $deferredCssBlock = "<script data-cfasync='false'>function lCss(url,media) {var d=document;var l=d.createElement('link');l.rel='stylesheet';l.type='text/css';l.href=url;l.media=media;aoin=d.getElementsByTagName('noscript')[0];aoin.parentNode.insertBefore(l,aoin.nextSibling);}function deferredCSS() {";
529
- $noScriptCssBlock = "<noscript>";
530
- $defer_inline_code=$this->defer_inline;
531
- $defer_inline_code=apply_filters( 'breeze_filter_css_defer_inline', $defer_inline_code );
532
- if(!empty($defer_inline_code)){
533
- $iCssHash=md5($defer_inline_code);
534
- $iCssCache = new Breeze_MinificationCache($iCssHash,'css');
535
- if($iCssCache->check()) {
536
- // we have the optimized inline CSS in cache
537
- $defer_inline_code=$iCssCache->retrieve();
538
- } else {
539
- if (class_exists('Minify_CSS_Compressor')) {
540
- $tmp_code = trim(Minify_CSS_Compressor::process($this->defer_inline));
541
- } else if(class_exists('CSSmin')) {
542
- $cssmin = new CSSmin();
543
- $tmp_code = trim($cssmin->run($defer_inline_code));
544
- }
545
- if (!empty($tmp_code)) {
546
- $defer_inline_code = $tmp_code;
547
- $iCssCache->cache($defer_inline_code,"text/css");
548
- unset($tmp_code);
549
- }
550
- }
551
- $code_out='<style type="text/css" id="aoatfcss" media="all">'.$defer_inline_code.'</style>';
552
- $this->inject_in_html($code_out,$replaceTag);
553
- }
554
- }
555
- foreach($this->url as $media => $url) {
556
- $url = $this->url_replace_cdn($url);
557
- //Add the stylesheet either deferred (import at bottom) or normal links in head
558
- if($this->defer == true) {
559
- $deferredCssBlock .= "lCss('".$url."','".$media."');";
560
- $noScriptCssBlock .= '<link type="text/css" media="'.$media.'" href="'.$url.'" rel="stylesheet" />';
561
- } else {
562
- if (strlen($this->csscode[$media]) > $this->cssinlinesize) {
563
- $this->inject_in_html('<link type="text/css" media="'.$media.'" href="'.$url.'" rel="stylesheet" />',$replaceTag);
564
- } else if (strlen($this->csscode[$media])>0) {
565
- $this->inject_in_html('<style type="text/css" media="'.$media.'">'.$this->csscode[$media].'</style>',$replaceTag);
566
- }
567
- }
568
- }
569
- if($this->defer == true) {
570
- $deferredCssBlock .= "}if(window.addEventListener){window.addEventListener('DOMContentLoaded',deferredCSS,false);}else{window.onload = deferredCSS;}</script>";
571
- $noScriptCssBlock .= "</noscript>";
572
- $this->inject_in_html($noScriptCssBlock,$replaceTag);
573
- $this->inject_in_html($deferredCssBlock,array('</body>','before'));
574
- }
575
- }
576
- }else{
577
- if ($this->inline == true) {
578
- foreach($this->csscode as $media => $code) {
579
- $this->inject_in_html('<style type="text/css" media="'.$media.'">'.$code.'</style>',$replaceTag);
580
- }
581
- } else {
582
- if ($this->defer == true) {
583
- $deferredCssBlock = "<script data-cfasync='false'>function lCss(url,media) {var d=document;var l=d.createElement('link');l.rel='stylesheet';l.type='text/css';l.href=url;l.media=media;aoin=d.getElementsByTagName('noscript')[0];aoin.parentNode.insertBefore(l,aoin.nextSibling);}function deferredCSS() {";
584
- $noScriptCssBlock = "<noscript>";
585
- $defer_inline_code=$this->defer_inline;
586
- $defer_inline_code=apply_filters( 'breeze_filter_css_defer_inline', $defer_inline_code );
587
- if(!empty($defer_inline_code)){
588
- $iCssHash=md5($defer_inline_code);
589
- $iCssCache = new Breeze_MinificationCache($iCssHash,'css');
590
- if($iCssCache->check()) {
591
- // we have the optimized inline CSS in cache
592
- $defer_inline_code=$iCssCache->retrieve();
593
- } else {
594
- if (class_exists('Minify_CSS_Compressor')) {
595
- $tmp_code = trim(Minify_CSS_Compressor::process($this->defer_inline));
596
- } else if(class_exists('CSSmin')) {
597
- $cssmin = new CSSmin();
598
- $tmp_code = trim($cssmin->run($defer_inline_code));
599
- }
600
- if (!empty($tmp_code)) {
601
- $defer_inline_code = $tmp_code;
602
- $iCssCache->cache($defer_inline_code,"text/css");
603
- unset($tmp_code);
604
- }
605
- }
606
- $code_out='<style type="text/css" id="aoatfcss" media="all">'.$defer_inline_code.'</style>';
607
- $this->inject_in_html($code_out,$replaceTag);
608
- }
609
- }
610
- foreach ($this->url_group_arr as $value){
611
- $media = substr($value,0,strpos($value,'_breezemedia_'));
612
- $code = substr($value,strpos($value,'_breezemedia_')+strlen('_breezemedia_'));
613
- $hash = substr($code,0,strpos($code,'_breezekey_'));
614
- $url = substr($code,strpos($code,'_breezekey_')+strlen('_breezekey_'));
615
- $cache = new Breeze_MinificationCache($hash,'css');
616
- if($cache->check()) {
617
- $csscode = $cache->retrieve();
618
- }
619
- //Add the stylesheet either deferred (import at bottom) or normal links in head
620
- if($this->defer == true) {
621
- $deferredCssBlock .= "lCss('".$url."','".$media."');";
622
- $noScriptCssBlock .= '<link type="text/css" media="'.$media.'" href="'.$url.'" rel="stylesheet" />';
623
- } else {
624
- if (strlen($csscode) > $this->cssinlinesize) {
625
- $url = $this->url_replace_cdn($url);
626
- $this->inject_in_html('<link type="text/css" media="'.$media.'" href="'.$url.'" rel="stylesheet" />',$replaceTag);
627
- } else if (strlen($csscode)>0) {
628
- $this->inject_in_html('<style type="text/css" media="'.$media.'">'.$csscode.'</style>',$replaceTag);
629
- }
630
- }
631
- }
632
- if($this->defer == true) {
633
- $deferredCssBlock .= "}if(window.addEventListener){window.addEventListener('DOMContentLoaded',deferredCSS,false);}else{window.onload = deferredCSS;}</script>";
634
- $noScriptCssBlock .= "</noscript>";
635
- $this->inject_in_html($noScriptCssBlock,$replaceTag);
636
- $this->inject_in_html($deferredCssBlock,array('</body>','before'));
637
- }
638
- }
639
- }
 
640
  //Return the modified stylesheet
641
  return $this->content;
642
  }
643
- static function fixurls($file,$code) {
644
- $file = str_replace(BREEZE_ROOT_DIR,'/',$file);
645
- $dir = dirname($file); //Like /wp-content
 
646
  // quick fix for import-troubles in e.g. arras theme
647
- $code=preg_replace('#@import ("|\')(.+?)\.css("|\')#','@import url("${2}.css")',$code);
648
- if(preg_match_all('#url\((?!data)(?!\#)(?!"\#)(.*)\)#Usi',$code,$matches)) {
649
  $replace = array();
650
- foreach($matches[1] as $k => $url) {
651
  // Remove quotes
652
- $url = trim($url," \t\n\r\0\x0B\"'");
653
- $noQurl = trim($url,"\"'");
654
- if ($url!==$noQurl) {
655
- $removedQuotes=true;
656
  } else {
657
- $removedQuotes=false;
658
  }
659
- $url=$noQurl;
660
- if(substr($url,0,1)=='/' || preg_match('#^(https?://|ftp://|data:)#i',$url)) {
661
  //URL is absolute
662
  continue;
663
  } else {
664
  // relative URL
665
- $newurl = preg_replace('/https?:/','',str_replace(" ","%20",breeze_WP_ROOT_URL.str_replace('//','/',$dir.'/'.$url)));
666
- $hash = md5($url);
667
- $code = str_replace($matches[0][$k],$hash,$code);
668
- if (!empty($removedQuotes)) {
669
- $replace[$hash] = 'url(\''.$newurl.'\')';
670
  } else {
671
- $replace[$hash] = 'url('.$newurl.')';
672
  }
673
  }
674
- }
675
  //Do the replacing here to avoid breaking URLs
676
- $code = str_replace(array_keys($replace),array_values($replace),$code);
677
- }
 
678
  return $code;
679
  }
680
- private function ismovable($tag) {
681
- if (!empty($this->whitelist)) {
682
- foreach ($this->whitelist as $match) {
683
- if(strpos($tag,$match)!==false) {
 
684
  return true;
685
  }
686
  }
 
687
  // no match with whitelist
688
  return false;
689
  } else {
690
- if (is_array($this->dontmove)) {
691
- foreach($this->dontmove as $match) {
692
- if(strpos($tag,$match)!==false) {
693
  //Matched something
694
  return false;
695
  }
696
  }
697
  }
 
698
  //If we're here it's safe to move
699
  return true;
700
  }
701
  }
702
- private function can_inject_late($cssPath,$css) {
703
- if ((strpos($cssPath,"min.css")===false) || ($this->inject_min_late!==true)) {
 
704
  // late-inject turned off or file not minified based on filename
705
  return false;
706
- } else if (strpos($css,"@import")!==false) {
707
  // can't late-inject files with imports as those need to be aggregated
708
  return false;
709
- } else if ( (strpos($css,"@font-face")!==false ) && ( apply_filters("breeze_filter_css_fonts_cdn",false)===true) && (!empty($this->cdn_url)) ) {
710
  // don't late-inject CSS with font-src's if fonts are set to be CDN'ed
711
  return false;
712
- } else if ( (($this->datauris == true) || (!empty($this->cdn_url))) && preg_match("#background[^;}]*url\(#Ui",$css) ) {
713
  // don't late-inject CSS with images if CDN is set OR is image inlining is on
714
  return false;
715
  } else {
2
  /*
3
  * Based on some work of autoptimize plugin
4
  */
5
+ if ( ! defined( 'ABSPATH' ) ) {
6
+ exit;
7
+ } // Exit if accessed directly
8
  class Breeze_MinificationStyles extends Breeze_MinificationBase {
9
  private $css = array();
10
  private $csscode = array();
22
  private $cssremovables = array();
23
  private $include_inline = false;
24
  private $inject_min_late = '';
25
+ private $group_css = false;
26
+ private $custom_css_exclude = array();
27
+ private $css_group_val = array();
28
+ private $css_min_arr = array();
29
+ private $issetminfile = false;
30
+ private $url_group_arr = array();
31
+
32
  //Reads the page and collects style tags
33
+ public function read( $options ) {
34
  $noptimizeCSS = apply_filters( 'breeze_filter_css_noptimize', false, $this->content );
35
+ if ( $noptimizeCSS ) {
36
+ return false;
37
+ }
38
  $whitelistCSS = apply_filters( 'breeze_filter_css_whitelist', '' );
39
+ if ( ! empty( $whitelistCSS ) ) {
40
+ $this->whitelist = array_filter( array_map( 'trim', explode( ",", $whitelistCSS ) ) );
41
  }
42
+ if ( $options['nogooglefont'] == true ) {
43
  $removableCSS = "fonts.googleapis.com";
44
  } else {
45
  $removableCSS = "";
46
  }
47
+ $removableCSS = apply_filters( 'breeze_filter_css_removables', $removableCSS );
48
+ if ( ! empty( $removableCSS ) ) {
49
+ $this->cssremovables = array_filter( array_map( 'trim', explode( ",", $removableCSS ) ) );
50
  }
51
+ $this->cssinlinesize = apply_filters( 'breeze_filter_css_inlinesize', 256 );
52
  // filter to "late inject minified CSS", default to true for now (it is faster)
53
+ $this->inject_min_late = apply_filters( 'breeze_filter_css_inject_min_late', true );
54
  // Remove everything that's not the header
55
+ if ( apply_filters( 'breeze_filter_css_justhead', $options['justhead'] ) == true ) {
56
+ $content = explode( '</head>', $this->content, 2 );
57
+ $this->content = $content[0] . '</head>';
58
  $this->restofcontent = $content[1];
59
  }
60
  // include inline?
61
+ if ( apply_filters( 'breeze_css_include_inline', $options['include_inline'] ) == true ) {
62
  $this->include_inline = true;
63
  }
64
+ // group css?
65
+ if ( apply_filters( 'breeze_css_include_inline', $options['groupcss'] ) == true ) {
66
+ $this->group_css = true;
67
+ }
68
+ //custom js exclude
69
+ if ( ! empty( $options['custom_css_exclude'] ) ) {
70
+ $this->custom_css_exclude = $options['custom_css_exclude'];
71
+ }
72
  // what CSS shouldn't be autoptimized
73
  $excludeCSS = $options['css_exclude'];
74
  $excludeCSS = apply_filters( 'breeze_filter_css_exclude', $excludeCSS );
75
+ if ( $excludeCSS !== "" ) {
76
+ $this->dontmove = array_filter( array_map( 'trim', explode( ",", $excludeCSS ) ) );
77
  } else {
78
  $this->dontmove = "";
79
  }
93
  // Store data: URIs setting for later use
94
  $this->datauris = $options['datauris'];
95
  // noptimize me
96
+ $this->content = $this->hide_noptimize( $this->content );
97
  // exclude (no)script, as those may contain CSS which should be left as is
98
+ if ( strpos( $this->content, '<script' ) !== false ) {
99
  $this->content = preg_replace_callback(
100
  '#<(?:no)?script.*?<\/(?:no)?script>#is',
101
+ function ( $matches ) {
102
+ return "%%SCRIPT" . breeze_HASH . "%%" . base64_encode( $matches[0] ) . "%%SCRIPT%%";
103
+ },
104
  $this->content
105
  );
106
  }
107
  // Save IE hacks
108
+ $this->content = $this->hide_iehacks( $this->content );
109
  // hide comments
110
+ $this->content = $this->hide_comments( $this->content );
111
  // Get <style> and <link>
112
+ if ( preg_match_all( '#(<style[^>]*>.*</style>)|(<link[^>]*stylesheet[^>]*>)#Usmi', $this->content, $matches ) ) {
113
+ foreach ( $matches[0] as $tag ) {
114
+ if ( $this->isremovable( $tag, $this->cssremovables ) ) {
115
+ $this->content = str_replace( $tag, '', $this->content );
116
+ } else if ( $this->ismovable( $tag ) ) {
117
  // Get the media
118
+ if ( strpos( $tag, 'media=' ) !== false ) {
119
+ preg_match( '#media=(?:"|\')([^>]*)(?:"|\')#Ui', $tag, $medias );
120
+ $medias = explode( ',', $medias[1] );
121
+ $media = array();
122
+ foreach ( $medias as $elem ) {
123
+ if ( empty( $elem ) ) {
124
+ $elem = "all";
125
+ }
126
  $media[] = $elem;
127
  }
128
  } else {
129
  // No media specified - applies to all
130
+ $media = array( 'all' );
131
  }
132
+ $media = apply_filters( 'breeze_filter_css_tagmedia', $media, $tag );
133
+ if ( preg_match( '#<link.*href=("|\')(.*)("|\')#Usmi', $tag, $source ) ) {
134
  // <link>
135
+ $url = current( explode( '?', $source[2], 2 ) );
136
+ // Let's check if this file is in the excluded list.
137
+ $is_excluded = breeze_is_string_in_array_values( $url, $this->custom_css_exclude );
138
+ //exclude css file
139
+ if ( ! empty( $is_excluded ) ) {
140
+ continue;
141
+ }
142
+ $path = $this->getpath( $url );
143
+ if ( $path !== false && preg_match( '#\.css$#', $path ) ) {
144
  // Good link
145
+ $this->css[] = array( $media, $path );
146
+ } else {
147
  // Link is dynamic (.php etc)
148
  $tag = '';
149
  }
150
  } else {
151
  // inline css in style tags can be wrapped in comment tags, so restore comments
152
+ $tag = $this->restore_comments( $tag );
153
+ preg_match( '#<style.*>(.*)</style>#Usmi', $tag, $code );
154
  // and re-hide them to be able to to the removal based on tag
155
+ $tag = $this->hide_comments( $tag );
156
  if ( $this->include_inline ) {
157
+ $code = preg_replace( '#^.*<!\[CDATA\[(?:\s*\*/)?(.*)(?://|/\*)\s*?\]\]>.*$#sm', '$1', $code[1] );
158
+ $this->css[] = array( $media, 'INLINE;' . $code );
159
  } else {
160
  $tag = '';
161
  }
162
  }
163
  // Remove the original style tag
164
+ $this->content = str_replace( $tag, '', $this->content );
165
  }
166
  }
167
+
168
  return true;
169
  }
170
+
171
  // Really, no styles?
172
  return false;
173
  }
174
+
175
  // Joins and optimizes CSS
176
  public function minify() {
177
+ foreach ( $this->css as $group ) {
178
+ list( $media, $css ) = $group;
179
+ if ( preg_match( '#^INLINE;#', $css ) ) {
180
  // <style>
181
+ $css = preg_replace( '#^INLINE;#', '', $css );
182
+ $css = $this->fixurls( ABSPATH . '/index.php', $css );
183
  $tmpstyle = apply_filters( 'breeze_css_individual_style', $css, "" );
184
+ if ( has_filter( 'breeze_css_individual_style' ) && ! empty( $tmpstyle ) ) {
185
+ $css = $tmpstyle;
186
+ $this->alreadyminified = true;
187
  }
188
  } else {
189
  //<link>
190
+ if ( $css !== false && file_exists( $css ) && is_readable( $css ) ) {
191
+ $cssPath = $css;
192
+ $css = $this->fixurls( $cssPath, file_get_contents( $cssPath ) );
193
+ $css = preg_replace( '/\x{EF}\x{BB}\x{BF}/', '', $css );
194
  $tmpstyle = apply_filters( 'breeze_css_individual_style', $css, $cssPath );
195
+ if ( has_filter( 'breeze_css_individual_style' ) && ! empty( $tmpstyle ) ) {
196
+ $css = $tmpstyle;
197
+ $this->alreadyminified = true;
198
+ } else if ( $this->can_inject_late( $cssPath, $css ) ) {
199
+ $css = "%%INJECTLATER" . breeze_HASH . "%%" . base64_encode( $cssPath ) . "|" . md5( $css ) . "%%INJECTLATER%%";
200
  }
201
  } else {
202
  // Couldn't read CSS. Maybe getpath isn't working?
203
  $css = '';
204
  }
205
  }
206
+ if ( $this->group_css == true ) {
207
+ foreach ( $media as $elem ) {
208
+ if ( ! isset( $this->csscode[ $elem ] ) ) {
209
+ $this->csscode[ $elem ] = '';
210
+ }
211
+ $this->csscode[ $elem ] .= "\n/*FILESTART*/" . $css;
212
+ }
213
+ } else {
214
+ foreach ( $media as $elem ) {
215
+ $this->css_group_val[] = $elem . "_breezecssgroup_" . $css;
216
+ }
217
+ }
218
+ }
219
+ if ( $this->group_css == true ) {
220
+ // Check for duplicate code
221
+ $md5list = array();
222
+ $tmpcss = $this->csscode;
223
+ foreach ( $tmpcss as $media => $code ) {
224
+ $md5sum = md5( $code );
225
+ $medianame = $media;
226
+ foreach ( $md5list as $med => $sum ) {
227
+ // If same code
228
+ if ( $sum === $md5sum ) {
229
+ //Add the merged code
230
+ $medianame = $med . ', ' . $media;
231
+ $this->csscode[ $medianame ] = $code;
232
+ $md5list[ $medianame ] = $md5list[ $med ];
233
+ unset( $this->csscode[ $med ], $this->csscode[ $media ] );
234
+ unset( $md5list[ $med ] );
235
+ }
236
+ }
237
+ $md5list[ $medianame ] = $md5sum;
238
+ }
239
+ unset( $tmpcss );
240
+ // Manage @imports, while is for recursive import management
241
+ foreach ( $this->csscode as &$thiscss ) {
242
+ // Flag to trigger import reconstitution and var to hold external imports
243
+ $fiximports = false;
244
+ $external_imports = "";
245
+ while ( preg_match_all( '#^(/*\s?)@import.*(?:;|$)#Um', $thiscss, $matches ) ) {
246
+ foreach ( $matches[0] as $import ) {
247
+ if ( $this->isremovable( $import, $this->cssremovables ) ) {
248
+ $thiscss = str_replace( $import, '', $thiscss );
249
+ $import_ok = true;
250
+ } else {
251
+ $url = trim( preg_replace( '#^.*((?:https?:|ftp:)?//.*\.css).*$#', '$1', trim( $import ) ), " \t\n\r\0\x0B\"'" );
252
+ $path = $this->getpath( $url );
253
+ $import_ok = false;
254
+ if ( file_exists( $path ) && is_readable( $path ) ) {
255
+ $code = addcslashes( $this->fixurls( $path, file_get_contents( $path ) ), "\\" );
256
+ $code = preg_replace( '/\x{EF}\x{BB}\x{BF}/', '', $code );
257
+ $tmpstyle = apply_filters( 'breeze_css_individual_style', $code, "" );
258
+ if ( has_filter( 'breeze_css_individual_style' ) && ! empty( $tmpstyle ) ) {
259
+ $code = $tmpstyle;
260
+ $this->alreadyminified = true;
261
+ } else if ( $this->can_inject_late( $path, $code ) ) {
262
+ $code = "%%INJECTLATER" . breeze_HASH . "%%" . base64_encode( $path ) . "|" . md5( $code ) . "%%INJECTLATER%%";
263
+ }
264
+ if ( ! empty( $code ) ) {
265
+ $tmp_thiscss = preg_replace( '#(/\*FILESTART\*/.*)' . preg_quote( $import, '#' ) . '#Us', '/*FILESTART2*/' . $code . '$1', $thiscss );
266
+ if ( ! empty( $tmp_thiscss ) ) {
267
+ $thiscss = $tmp_thiscss;
268
+ $import_ok = true;
269
+ unset( $tmp_thiscss );
270
+ }
271
+ unset( $code );
272
+ }
273
+ }
274
+ }
275
+ if ( ! $import_ok ) {
276
+ // external imports and general fall-back
277
+ $external_imports .= $import;
278
+ $thiscss = str_replace( $import, '', $thiscss );
279
+ $fiximports = true;
280
+ }
281
+ }
282
+ $thiscss = preg_replace( '#/\*FILESTART\*/#', '', $thiscss );
283
+ $thiscss = preg_replace( '#/\*FILESTART2\*/#', '/*FILESTART*/', $thiscss );
284
+ }
285
+ // add external imports to top of aggregated CSS
286
+ if ( $fiximports ) {
287
+ $thiscss = $external_imports . $thiscss;
288
+ }
289
+ }
290
+ unset( $thiscss );
291
+ // $this->csscode has all the uncompressed code now.
292
+ $mhtmlcount = 0;
293
+ foreach ( $this->csscode as &$code ) {
294
+ // Check for already-minified code
295
+ $hash = md5( $code );
296
+ $ccheck = new Breeze_MinificationCache( $hash, 'css' );
297
+ if ( $ccheck->check() ) {
298
+ $code = $ccheck->retrieve();
299
+ $this->hashmap[ md5( $code ) ] = $hash;
300
+ continue;
301
+ }
302
+ unset( $ccheck );
303
+ // Do the imaging!
304
+ $imgreplace = array();
305
+ preg_match_all( '#(background[^;}]*url\((?!\s?"?\s?data)(.*)\)[^;}]*)(?:;|$|})#Usm', $code, $matches );
306
+ if ( ( $this->datauris == true ) && ( function_exists( 'base64_encode' ) ) && ( is_array( $matches ) ) ) {
307
+ foreach ( $matches[2] as $count => $quotedurl ) {
308
+ $iurl = trim( $quotedurl, " \t\n\r\0\x0B\"'" );
309
+ // if querystring, remove it from url
310
+ if ( strpos( $iurl, '?' ) !== false ) {
311
+ $iurl = strtok( $iurl, '?' );
312
+ }
313
+ $ipath = $this->getpath( $iurl );
314
+ $datauri_max_size = 4096;
315
+ $datauri_max_size = (int) apply_filters( 'breeze_filter_css_datauri_maxsize', $datauri_max_size );
316
+ $datauri_exclude = apply_filters( 'breeze_filter_css_datauri_exclude', "" );
317
+ if ( ! empty( $datauri_exclude ) ) {
318
+ $no_datauris = array_filter( array_map( 'trim', explode( ",", $datauri_exclude ) ) );
319
+ foreach ( $no_datauris as $no_datauri ) {
320
+ if ( strpos( $iurl, $no_datauri ) !== false ) {
321
+ $ipath = false;
322
+ break;
323
+ }
324
+ }
325
+ }
326
+ if ( $ipath != false && preg_match( '#\.(jpe?g|png|gif|bmp)$#i', $ipath ) && file_exists( $ipath ) && is_readable( $ipath ) && filesize( $ipath ) <= $datauri_max_size ) {
327
+ $ihash = md5( $ipath );
328
+ $icheck = new Breeze_MinificationCache( $ihash, 'img' );
329
+ if ( $icheck->check() ) {
330
+ // we have the base64 image in cache
331
+ $headAndData = $icheck->retrieve();
332
+ $_base64data = explode( ";base64,", $headAndData );
333
+ $base64data = $_base64data[1];
334
+ } else {
335
+ // It's an image and we don't have it in cache, get the type
336
+ $explA = explode( '.', $ipath );
337
+ $type = end( $explA );
338
+ switch ( $type ) {
339
+ case 'jpeg':
340
+ $dataurihead = 'data:image/jpeg;base64,';
341
+ break;
342
+ case 'jpg':
343
+ $dataurihead = 'data:image/jpeg;base64,';
344
+ break;
345
+ case 'gif':
346
+ $dataurihead = 'data:image/gif;base64,';
347
+ break;
348
+ case 'png':
349
+ $dataurihead = 'data:image/png;base64,';
350
+ break;
351
+ case 'bmp':
352
+ $dataurihead = 'data:image/bmp;base64,';
353
+ break;
354
+ default:
355
+ $dataurihead = 'data:application/octet-stream;base64,';
356
+ }
357
+ // Encode the data
358
+ $base64data = base64_encode( file_get_contents( $ipath ) );
359
+ $headAndData = $dataurihead . $base64data;
360
+ // Save in cache
361
+ $icheck->cache( $headAndData, "text/plain" );
362
+ }
363
+ unset( $icheck );
364
+ // Add it to the list for replacement
365
+ $imgreplace[ $matches[1][ $count ] ] = str_replace( $quotedurl, $headAndData, $matches[1][ $count ] ) . ";\n*" . str_replace( $quotedurl, 'mhtml:%%MHTML%%!' . $mhtmlcount, $matches[1][ $count ] ) . ";\n_" . $matches[1][ $count ] . ';';
366
+ // Store image on the mhtml document
367
+ $this->mhtml .= "--_\r\nContent-Location:{$mhtmlcount}\r\nContent-Transfer-Encoding:base64\r\n\r\n{$base64data}\r\n";
368
+ $mhtmlcount ++;
369
+ } else {
370
+ // just cdn the URL if applicable
371
+ if ( ! empty( $this->cdn_url ) ) {
372
+ $url = trim( $quotedurl, " \t\n\r\0\x0B\"'" );
373
+ $cdn_url = $this->url_replace_cdn( $url );
374
+ $imgreplace[ $matches[1][ $count ] ] = str_replace( $quotedurl, $cdn_url, $matches[1][ $count ] );
375
+ }
376
+ }
377
+ }
378
+ } else if ( ( is_array( $matches ) ) && ( ! empty( $this->cdn_url ) ) ) {
379
+ // change background image urls to cdn-url
380
+ foreach ( $matches[2] as $count => $quotedurl ) {
381
+ $url = trim( $quotedurl, " \t\n\r\0\x0B\"'" );
382
+ $cdn_url = $this->url_replace_cdn( $url );
383
+ $imgreplace[ $matches[1][ $count ] ] = str_replace( $quotedurl, $cdn_url, $matches[1][ $count ] );
384
+ }
385
+ }
386
+ if ( ! empty( $imgreplace ) ) {
387
+ $code = str_replace( array_keys( $imgreplace ), array_values( $imgreplace ), $code );
388
+ }
389
+ // CDN the fonts!
390
+ if ( ( ! empty( $this->cdn_url ) ) && ( apply_filters( 'breeze_filter_css_fonts_cdn', false ) ) && ( version_compare( PHP_VERSION, '5.3.0' ) >= 0 ) ) {
391
+ $fontreplace = array();
392
+ include_once( BREEZE_PLUGIN_DIR . 'inc/minification/config/minificationFontRegex.php' );
393
+ preg_match_all( $fonturl_regex, $code, $matches );
394
+ if ( is_array( $matches ) ) {
395
+ foreach ( $matches[8] as $count => $quotedurl ) {
396
+ $url = trim( $quotedurl, " \t\n\r\0\x0B\"'" );
397
+ $cdn_url = $this->url_replace_cdn( $url );
398
+ $fontreplace[ $matches[8][ $count ] ] = str_replace( $quotedurl, $cdn_url, $matches[8][ $count ] );
399
+ }
400
+ if ( ! empty( $fontreplace ) ) {
401
+ $code = str_replace( array_keys( $fontreplace ), array_values( $fontreplace ), $code );
402
+ }
403
+ }
404
+ }
405
+ // Minify
406
+ if ( ( $this->alreadyminified !== true ) && ( apply_filters( "breeze_css_do_minify", true ) ) ) {
407
+ if ( class_exists( 'Minify_CSS_Compressor' ) ) {
408
+ $tmp_code = trim( Minify_CSS_Compressor::process( $code ) );
409
+ } else if ( class_exists( 'CSSmin' ) ) {
410
+ $cssmin = new CSSmin();
411
+ if ( method_exists( $cssmin, "run" ) ) {
412
+ $tmp_code = trim( $cssmin->run( $code ) );
413
+ } elseif ( @is_callable( array( $cssmin, "minify" ) ) ) {
414
+ $tmp_code = trim( CssMin::minify( $code ) );
415
+ }
416
+ }
417
+ if ( ! empty( $tmp_code ) ) {
418
+ $code = $tmp_code;
419
+ unset( $tmp_code );
420
+ }
421
+ }
422
+ $code = $this->inject_minified( $code );
423
+ $tmp_code = apply_filters( 'breeze_css_after_minify', $code );
424
+ if ( ! empty( $tmp_code ) ) {
425
+ $code = $tmp_code;
426
+ unset( $tmp_code );
427
+ }
428
+ $this->hashmap[ md5( $code ) ] = $hash;
429
+ }
430
+ unset( $code );
431
+ } else {
432
+ foreach ( $this->css_group_val as $value ) {
433
+ $media = substr( $value, 0, strpos( $value, '_breezecssgroup_' ) );
434
+ $css = substr( $value, strpos( $value, '_breezecssgroup_' ) + strlen( '_breezecssgroup_' ) );
435
+ $hash = md5( $css );
436
+ $ccheck = new Breeze_MinificationCache( $hash, 'css' );
437
+ if ( $ccheck->check() ) {
438
+ $css_exist = $ccheck->retrieve();
439
+ $this->css_min_arr[] = $media . "_breezemedia_" . $hash . "_breezekey_" . $css_exist;
440
+ continue;
441
+ }
442
+ unset( $ccheck );
443
+ // Minify
444
+ if ( class_exists( 'Minify_CSS_Compressor' ) ) {
445
+ $tmp_code = trim( Minify_CSS_Compressor::process( $css ) );
446
+ } else if ( class_exists( 'CSSmin' ) ) {
447
+ $cssmin = new CSSmin();
448
+ if ( method_exists( $cssmin, "run" ) ) {
449
+ $tmp_code = trim( $cssmin->run( $css ) );
450
+ } elseif ( @is_callable( array( $cssmin, "minify" ) ) ) {
451
+ $tmp_code = trim( CssMin::minify( $css ) );
452
+ }
453
+ }
454
+ if ( ! empty( $tmp_code ) ) {
455
+ $css = $tmp_code;
456
+ unset( $tmp_code );
457
+ }
458
+ $css = $this->inject_minified( $css );
459
+ $css = apply_filters( 'breeze_css_after_minify', $css );
460
+ $this->css_min_arr[] = $media . "_breezemedia_" . $hash . "_breezekey_" . $css;
461
+ }
462
+ unset( $css );
463
+ }
464
+
465
  return true;
466
  }
467
+
468
  //Caches the CSS in uncompressed, deflated and gzipped form.
469
  public function cache() {
470
+ if ( $this->datauris ) {
471
  // MHTML Preparation
472
+ $this->mhtml = "/*\r\nContent-Type: multipart/related; boundary=\"_\"\r\n\r\n" . $this->mhtml . "*/\r\n";
473
+ $md5 = md5( $this->mhtml );
474
+ $cache = new Breeze_MinificationCache( $md5, 'txt' );
475
+ if ( ! $cache->check() ) {
476
  // Cache our images for IE
477
+ $cache->cache( $this->mhtml, 'text/plain' );
478
+ }
479
+ $mhtml = breeze_CACHE_URL . $cache->getname();
480
+ }
481
+ if ( $this->group_css == true ) {
482
+ // CSS cache
483
+ foreach ( $this->csscode as $media => $code ) {
484
+ $md5 = $this->hashmap[ md5( $code ) ];
485
+ if ( $this->datauris ) {
486
+ // Images for ie! Get the right url
487
+ $code = str_replace( '%%MHTML%%', $mhtml, $code );
488
+ }
489
+ $cache = new Breeze_MinificationCache( $md5, 'css' );
490
+ if ( ! $cache->check() ) {
491
+ // Cache our code
492
+ $cache->cache( $code, 'text/css' );
493
+ }
494
+ $this->url[ $media ] = breeze_CACHE_URL . $cache->getname();
495
+ }
496
+ } else {
497
+ foreach ( $this->css_min_arr as $value ) {
498
+ $media = substr( $value, 0, strpos( $value, '_breezemedia_' ) );
499
+ $code = substr( $value, strpos( $value, '_breezemedia_' ) + strlen( '_breezemedia_' ) );
500
+ $hash = substr( $code, 0, strpos( $code, '_breezekey_' ) );
501
+ $css = substr( $code, strpos( $code, '_breezekey_' ) + strlen( '_breezekey_' ) );
502
+ $cache = new Breeze_MinificationCache( $hash, 'css' );
503
+ if ( ! $cache->check() ) {
504
+ // Cache our code
505
+ $cache->cache( $css, 'text/css' );
506
+ }
507
+ $this->url_group_arr[] = $media . "_breezemedia_" . $hash . "_breezekey_" . breeze_CACHE_URL . $cache->getname();
508
  }
 
509
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
510
  }
511
+
512
  //Returns the content
513
  public function getcontent() {
514
  // restore IE hacks
515
+ $this->content = $this->restore_iehacks( $this->content );
516
  // restore comments
517
+ $this->content = $this->restore_comments( $this->content );
518
  // restore (no)script
519
+ if ( strpos( $this->content, '%%SCRIPT%%' ) !== false ) {
520
  $this->content = preg_replace_callback(
521
+ '#%%SCRIPT' . breeze_HASH . '%%(.*?)%%SCRIPT%%#is',
522
 
523
+ function ( $matches ) {
524
+ return base64_decode( $matches[1] );
525
+ },
526
  $this->content
527
  );
528
  }
529
  // restore noptimize
530
+ $this->content = $this->restore_noptimize( $this->content );
531
  //Restore the full content
532
+ if ( ! empty( $this->restofcontent ) ) {
533
+ $this->content .= $this->restofcontent;
534
  $this->restofcontent = '';
535
  }
536
  // Inject the new stylesheets
537
+ $replaceTag = array( "<title", "before" );
538
  $replaceTag = apply_filters( 'breeze_filter_css_replacetag', $replaceTag );
539
+ if ( $this->group_css == true ) {
540
+ if ( $this->inline == true ) {
541
+ foreach ( $this->csscode as $media => $code ) {
542
+ $this->inject_in_html( '<style type="text/css" media="' . $media . '">' . $code . '</style>', $replaceTag );
543
+ }
544
+ } else {
545
+ if ( $this->defer == true ) {
546
+ $deferredCssBlock = "<script data-cfasync='false'>function lCss(url,media) {var d=document;var l=d.createElement('link');l.rel='stylesheet';l.type='text/css';l.href=url;l.media=media;aoin=d.getElementsByTagName('noscript')[0];aoin.parentNode.insertBefore(l,aoin.nextSibling);}function deferredCSS() {";
547
+ $noScriptCssBlock = "<noscript>";
548
+ $defer_inline_code = $this->defer_inline;
549
+ $defer_inline_code = apply_filters( 'breeze_filter_css_defer_inline', $defer_inline_code );
550
+ if ( ! empty( $defer_inline_code ) ) {
551
+ $iCssHash = md5( $defer_inline_code );
552
+ $iCssCache = new Breeze_MinificationCache( $iCssHash, 'css' );
553
+ if ( $iCssCache->check() ) {
554
+ // we have the optimized inline CSS in cache
555
+ $defer_inline_code = $iCssCache->retrieve();
556
+ } else {
557
+ if ( class_exists( 'Minify_CSS_Compressor' ) ) {
558
+ $tmp_code = trim( Minify_CSS_Compressor::process( $this->defer_inline ) );
559
+ } else if ( class_exists( 'CSSmin' ) ) {
560
+ $cssmin = new CSSmin();
561
+ $tmp_code = trim( $cssmin->run( $defer_inline_code ) );
562
+ }
563
+ if ( ! empty( $tmp_code ) ) {
564
+ $defer_inline_code = $tmp_code;
565
+ $iCssCache->cache( $defer_inline_code, "text/css" );
566
+ unset( $tmp_code );
567
+ }
568
+ }
569
+ $code_out = '<style type="text/css" id="aoatfcss" media="all">' . $defer_inline_code . '</style>';
570
+ $this->inject_in_html( $code_out, $replaceTag );
571
+ }
572
+ }
573
+ foreach ( $this->url as $media => $url ) {
574
+ $url = $this->url_replace_cdn( $url );
575
+ //Add the stylesheet either deferred (import at bottom) or normal links in head
576
+ if ( $this->defer == true ) {
577
+ $deferredCssBlock .= "lCss('" . $url . "','" . $media . "');";
578
+ $noScriptCssBlock .= '<link type="text/css" media="' . $media . '" href="' . $url . '" rel="stylesheet" />';
579
+ } else {
580
+ if ( strlen( $this->csscode[ $media ] ) > $this->cssinlinesize ) {
581
+ $this->inject_in_html( '<link type="text/css" media="' . $media . '" href="' . $url . '" rel="stylesheet" />', $replaceTag );
582
+ } else if ( strlen( $this->csscode[ $media ] ) > 0 ) {
583
+ $this->inject_in_html( '<style type="text/css" media="' . $media . '">' . $this->csscode[ $media ] . '</style>', $replaceTag );
584
+ }
585
+ }
586
+ }
587
+ if ( $this->defer == true ) {
588
+ $deferredCssBlock .= "}if(window.addEventListener){window.addEventListener('DOMContentLoaded',deferredCSS,false);}else{window.onload = deferredCSS;}</script>";
589
+ $noScriptCssBlock .= "</noscript>";
590
+ $this->inject_in_html( $noScriptCssBlock, $replaceTag );
591
+ $this->inject_in_html( $deferredCssBlock, array( '</body>', 'before' ) );
592
+ }
593
+ }
594
+ } else {
595
+ if ( $this->inline == true ) {
596
+ foreach ( $this->csscode as $media => $code ) {
597
+ $this->inject_in_html( '<style type="text/css" media="' . $media . '">' . $code . '</style>', $replaceTag );
598
+ }
599
+ } else {
600
+ if ( $this->defer == true ) {
601
+ $deferredCssBlock = "<script data-cfasync='false'>function lCss(url,media) {var d=document;var l=d.createElement('link');l.rel='stylesheet';l.type='text/css';l.href=url;l.media=media;aoin=d.getElementsByTagName('noscript')[0];aoin.parentNode.insertBefore(l,aoin.nextSibling);}function deferredCSS() {";
602
+ $noScriptCssBlock = "<noscript>";
603
+ $defer_inline_code = $this->defer_inline;
604
+ $defer_inline_code = apply_filters( 'breeze_filter_css_defer_inline', $defer_inline_code );
605
+ if ( ! empty( $defer_inline_code ) ) {
606
+ $iCssHash = md5( $defer_inline_code );
607
+ $iCssCache = new Breeze_MinificationCache( $iCssHash, 'css' );
608
+ if ( $iCssCache->check() ) {
609
+ // we have the optimized inline CSS in cache
610
+ $defer_inline_code = $iCssCache->retrieve();
611
+ } else {
612
+ if ( class_exists( 'Minify_CSS_Compressor' ) ) {
613
+ $tmp_code = trim( Minify_CSS_Compressor::process( $this->defer_inline ) );
614
+ } else if ( class_exists( 'CSSmin' ) ) {
615
+ $cssmin = new CSSmin();
616
+ $tmp_code = trim( $cssmin->run( $defer_inline_code ) );
617
+ }
618
+ if ( ! empty( $tmp_code ) ) {
619
+ $defer_inline_code = $tmp_code;
620
+ $iCssCache->cache( $defer_inline_code, "text/css" );
621
+ unset( $tmp_code );
622
+ }
623
+ }
624
+ $code_out = '<style type="text/css" id="aoatfcss" media="all">' . $defer_inline_code . '</style>';
625
+ $this->inject_in_html( $code_out, $replaceTag );
626
+ }
627
+ }
628
+ foreach ( $this->url_group_arr as $value ) {
629
+ $media = substr( $value, 0, strpos( $value, '_breezemedia_' ) );
630
+ $code = substr( $value, strpos( $value, '_breezemedia_' ) + strlen( '_breezemedia_' ) );
631
+ $hash = substr( $code, 0, strpos( $code, '_breezekey_' ) );
632
+ $url = substr( $code, strpos( $code, '_breezekey_' ) + strlen( '_breezekey_' ) );
633
+ $cache = new Breeze_MinificationCache( $hash, 'css' );
634
+ if ( $cache->check() ) {
635
+ $csscode = $cache->retrieve();
636
+ }
637
+ //Add the stylesheet either deferred (import at bottom) or normal links in head
638
+ if ( $this->defer == true ) {
639
+ $deferredCssBlock .= "lCss('" . $url . "','" . $media . "');";
640
+ $noScriptCssBlock .= '<link type="text/css" media="' . $media . '" href="' . $url . '" rel="stylesheet" />';
641
+ } else {
642
+ if ( strlen( $csscode ) > $this->cssinlinesize ) {
643
+ $url = $this->url_replace_cdn( $url );
644
+ $this->inject_in_html( '<link type="text/css" media="' . $media . '" href="' . $url . '" rel="stylesheet" />', $replaceTag );
645
+ } else if ( strlen( $csscode ) > 0 ) {
646
+ $this->inject_in_html( '<style type="text/css" media="' . $media . '">' . $csscode . '</style>', $replaceTag );
647
+ }
648
+ }
649
+ }
650
+ if ( $this->defer == true ) {
651
+ $deferredCssBlock .= "}if(window.addEventListener){window.addEventListener('DOMContentLoaded',deferredCSS,false);}else{window.onload = deferredCSS;}</script>";
652
+ $noScriptCssBlock .= "</noscript>";
653
+ $this->inject_in_html( $noScriptCssBlock, $replaceTag );
654
+ $this->inject_in_html( $deferredCssBlock, array( '</body>', 'before' ) );
655
+ }
656
+ }
657
+ }
658
+
659
  //Return the modified stylesheet
660
  return $this->content;
661
  }
662
+
663
+ static function fixurls( $file, $code ) {
664
+ $file = str_replace( BREEZE_ROOT_DIR, '/', $file );
665
+ $dir = dirname( $file ); //Like /wp-content
666
  // quick fix for import-troubles in e.g. arras theme
667
+ $code = preg_replace( '#@import ("|\')(.+?)\.css("|\')#', '@import url("${2}.css")', $code );
668
+ if ( preg_match_all( '#url\((?!data)(?!\#)(?!"\#)(.*)\)#Usi', $code, $matches ) ) {
669
  $replace = array();
670
+ foreach ( $matches[1] as $k => $url ) {
671
  // Remove quotes
672
+ $url = trim( $url, " \t\n\r\0\x0B\"'" );
673
+ $noQurl = trim( $url, "\"'" );
674
+ if ( $url !== $noQurl ) {
675
+ $removedQuotes = true;
676
  } else {
677
+ $removedQuotes = false;
678
  }
679
+ $url = $noQurl;
680
+ if ( substr( $url, 0, 1 ) == '/' || preg_match( '#^(https?://|ftp://|data:)#i', $url ) ) {
681
  //URL is absolute
682
  continue;
683
  } else {
684
  // relative URL
685
+ $newurl = preg_replace( '/https?:/', '', str_replace( " ", "%20", breeze_WP_ROOT_URL . str_replace( '//', '/', $dir . '/' . $url ) ) );
686
+ $hash = md5( $url );
687
+ $code = str_replace( $matches[0][ $k ], $hash, $code );
688
+ if ( ! empty( $removedQuotes ) ) {
689
+ $replace[ $hash ] = 'url(\'' . $newurl . '\')';
690
  } else {
691
+ $replace[ $hash ] = 'url(' . $newurl . ')';
692
  }
693
  }
694
+ }
695
  //Do the replacing here to avoid breaking URLs
696
+ $code = str_replace( array_keys( $replace ), array_values( $replace ), $code );
697
+ }
698
+
699
  return $code;
700
  }
701
+
702
+ private function ismovable( $tag ) {
703
+ if ( ! empty( $this->whitelist ) ) {
704
+ foreach ( $this->whitelist as $match ) {
705
+ if ( strpos( $tag, $match ) !== false ) {
706
  return true;
707
  }
708
  }
709
+
710
  // no match with whitelist
711
  return false;
712
  } else {
713
+ if ( is_array( $this->dontmove ) ) {
714
+ foreach ( $this->dontmove as $match ) {
715
+ if ( strpos( $tag, $match ) !== false ) {
716
  //Matched something
717
  return false;
718
  }
719
  }
720
  }
721
+
722
  //If we're here it's safe to move
723
  return true;
724
  }
725
  }
726
+
727
+ private function can_inject_late( $cssPath, $css ) {
728
+ if ( ( strpos( $cssPath, "min.css" ) === false ) || ( $this->inject_min_late !== true ) ) {
729
  // late-inject turned off or file not minified based on filename
730
  return false;
731
+ } else if ( strpos( $css, "@import" ) !== false ) {
732
  // can't late-inject files with imports as those need to be aggregated
733
  return false;
734
+ } else if ( ( strpos( $css, "@font-face" ) !== false ) && ( apply_filters( "breeze_filter_css_fonts_cdn", false ) === true ) && ( ! empty( $this->cdn_url ) ) ) {
735
  // don't late-inject CSS with font-src's if fonts are set to be CDN'ed
736
  return false;
737
+ } else if ( ( ( $this->datauris == true ) || ( ! empty( $this->cdn_url ) ) ) && preg_match( "#background[^;}]*url\(#Ui", $css ) ) {
738
  // don't late-inject CSS with images if CDN is set OR is image inlining is on
739
  return false;
740
  } else {
readme.txt CHANGED
@@ -2,8 +2,8 @@
2
  Contributors: Cloudways
3
  Tags: cache,caching, performance, wp-cache, cdn, combine, compress, speed plugin, database cache,gzip, http compression, js cache, minify, optimize, page cache, performance, speed, expire headers
4
  Requires at least: 4.5
5
- Tested up to: 5.2.1
6
- Stable tag: 1.1.1
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
@@ -145,6 +145,11 @@ Using Gzip, Breeze compresses the request files, further reducing the size of th
145
 
146
  == Changelog ==
147
 
 
 
 
 
 
148
  = 1.1.1 =
149
  * Fix: Removed the use of remote JS. Now uses built-in version of jQuery Libraries.
150
 
2
  Contributors: Cloudways
3
  Tags: cache,caching, performance, wp-cache, cdn, combine, compress, speed plugin, database cache,gzip, http compression, js cache, minify, optimize, page cache, performance, speed, expire headers
4
  Requires at least: 4.5
5
+ Tested up to: 5.3
6
+ Stable tag: 1.1.2
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
145
 
146
  == Changelog ==
147
 
148
+ = 1.1.2 =
149
+ * Fix: Improved handling of exclusion of CSS and JS while Minification and Group Files options are enabled.
150
+ * Fix: Allow wildcard (.*) based exclusion of pattern files/URIs in exclude JS and exclude CSS fields.
151
+ * Fix: Increase the duration for leverage browser cacheable objects
152
+
153
  = 1.1.1 =
154
  * Fix: Removed the use of remote JS. Now uses built-in version of jQuery Libraries.
155
 
views/tabs/advanced.php CHANGED
@@ -1,177 +1,220 @@
1
- <?php
2
- defined('ABSPATH') or die;
3
-
4
- $advanced = breeze_get_option( 'advanced_settings', true );
5
- ?>
6
- <table cellspacing="15">
7
- <tr>
8
- <td>
9
- <label for="exclude-urls" class="breeze_tool_tip"><?php _e('Never Cache these URLs', 'breeze'); ?></label>
10
- </td>
11
- <td>
12
- <textarea cols="100" rows="7" id="exclude-urls"
13
- name="exclude-urls"><?php if (!empty($advanced['breeze-exclude-urls'])) {
14
- $output = implode("\n", $advanced['breeze-exclude-urls']);
15
- echo esc_textarea($output);
16
- } ?></textarea>
17
- <br/>
18
- <span class="breeze_tool_tip"><b>Note:&nbsp;</b><?php _e('Add the URLs of the pages (one per line) you wish to exclude from the WordPress internal cache. To exclude URLs from the Varnish cache, please refer to this ', 'breeze') ?><a href="https://support.cloudways.com/how-to-exclude-url-from-varnish/" target="_blank"><?php _e('Knowledge Base','breeze')?></a><?php _e(' article.','breeze')?> </span>
19
- </td>
20
- </tr>
21
- <tr>
22
- <td>
23
- <label class="breeze_tool_tip"><?php _e('Group Files', 'breeze'); ?></label>
24
- </td>
25
- <td>
26
- <ul>
27
- <li>
28
- <input type="checkbox" name="group-css" id="group-css"
29
- value="1" <?php checked($advanced['breeze-group-css'],'1')?>/>
30
- <label class="breeze_tool_tip" for="group-css"><?php _e('CSS','breeze')?></label>
31
- </li>
32
- <li>
33
- <input type="checkbox" name="group-js" id="group-js"
34
- value="1" <?php checked($advanced['breeze-group-js'],'1')?>/>
35
- <label class="breeze_tool_tip" for="group-js"><?php _e('JS','breeze')?></label>
36
- </li>
37
- <li>
38
- <span class="breeze_tool_tip">
39
- <b>Note:&nbsp;</b><?php _e('Group CSS and JS files to combine them into a single file. This will reduce the number of HTTP requests to your server.', 'breeze') ?><br>
40
- <b><?php _e('Important: Enable Minification to use this option.','breeze')?></b>
41
- </span>
42
- </li>
43
- </ul>
44
- </td>
45
- </tr>
46
- <tr>
47
- <td>
48
- <label for="exclude-css" class="breeze_tool_tip"><?php _e('Exclude CSS', 'breeze') ?></label>
49
- </td>
50
- <td>
51
- <textarea cols="100" rows="7" id="exclude-css"
52
- name="exclude-css"><?php if (!empty($advanced['breeze-exclude-css'])) {
53
- $output = implode("\n", $advanced['breeze-exclude-css']);
54
- echo esc_textarea($output);
55
- } ?></textarea>
56
- <br/>
57
- <span class="breeze_tool_tip"><b>Note:&nbsp;</b><?php _e('Use this option to exclude CSS files from Minification and Grouping. Enter the URLs of CSS files on each line.', 'breeze') ?></span>
58
- </td>
59
- </tr>
60
- <tr>
61
- <td>
62
- <label for="exclude-js" class="breeze_tool_tip"><?php _e('Exclude JS', 'breeze') ?></label>
63
- </td>
64
- <td>
65
- <textarea cols="100" rows="7" id="exclude-js"
66
- name="exclude-js"><?php if (!empty($advanced['breeze-exclude-js'])) {
67
- $output = implode("\n", $advanced['breeze-exclude-js']);
68
- echo esc_textarea($output);
69
- } ?></textarea>
70
- <br/>
71
- <span class="breeze_tool_tip"><b>Note:&nbsp;</b><?php _e('Use this option to exclude JS files from Minification and Grouping. Enter the URLs of JS files on each line.', 'breeze') ?></span>
72
- </td>
73
- </tr>
74
- <tr>
75
- <td>
76
- <label for="move-to-footer-js" class="breeze_tool_tip"><?php _e('Move JS files to footer', 'breeze') ?></label>
77
- </td>
78
- <td>
79
- <div class="breeze-list-url">
80
- <?php if (!empty($advanced['breeze-move-to-footer-js'])) : ?>
81
- <?php foreach ($advanced['breeze-move-to-footer-js'] as $js_url) : ?>
82
- <div class="breeze-input-group">
83
- <span class="sort-handle">
84
- <span class="dashicons dashicons-arrow-up moveUp"></span>
85
- <span class="dashicons dashicons-arrow-down moveDown"></span>
86
- </span>
87
- <input type="text" size="98"
88
- class="breeze-input-url"
89
- name="move-to-footer-js[]"
90
- placeholder="<?php _e('Enter URL...', 'breeze') ?>"
91
- value="<?php echo esc_html($js_url) ?>" />
92
- <span class="dashicons dashicons-no item-remove" title="<?php _e('Remove', 'breeze') ?>"></span>
93
- </div>
94
- <?php endforeach; ?>
95
- <?php else : ?>
96
- <div class="breeze-input-group">
97
- <span class="sort-handle">
98
- <span class="dashicons dashicons-arrow-up moveUp"></span>
99
- <span class="dashicons dashicons-arrow-down moveDown"></span>
100
- </span>
101
- <input type="text" size="98"
102
- class="breeze-input-url"
103
- id="move-to-footer-js"
104
- name="move-to-footer-js[]"
105
- placeholder="<?php _e('Enter URL...', 'breeze') ?>"
106
- value="" />
107
- <span class="dashicons dashicons-no" title="<?php _e('Remove', 'breeze') ?>"></span>
108
- </div>
109
- <?php endif; ?>
110
- </div>
111
- <div style="margin: 10px 0">
112
- <button type="button" class="button add-url" id="add-move-to-footer-js">
113
- <?php _e('Add URL', 'breeze') ?>
114
- </button>
115
- </div>
116
- <div>
117
- <span class="breeze_tool_tip">
118
- <b>Note:&nbsp;</b>
119
- <?php _e('Enter the complete URLs of JS files to be moved to the footer during minification process.', 'breeze') ?>
120
- </span>
121
- <span class="breeze_tool_tip">
122
- <?php _e('You should add the URL of original files as URL of minified files are not supported.', 'breeze') ?>
123
- </span>
124
- </div>
125
- </td>
126
- </tr>
127
- <tr>
128
- <td>
129
- <label for="defer-js" class="breeze_tool_tip"><?php _e('JS files with deferred loading', 'breeze') ?></label>
130
- </td>
131
- <td>
132
- <div class="breeze-list-url">
133
- <?php if (!empty($advanced['breeze-defer-js'])) : ?>
134
- <?php foreach ($advanced['breeze-defer-js'] as $js_url) : ?>
135
- <div class="breeze-input-group">
136
- <span class="sort-handle">
137
- <span class="dashicons dashicons-arrow-up moveUp"></span>
138
- <span class="dashicons dashicons-arrow-down moveDown"></span>
139
- </span>
140
- <input type="text" size="98"
141
- class="breeze-input-url"
142
- name="defer-js[]"
143
- placeholder="<?php _e('Enter URL...', 'breeze') ?>"
144
- value="<?php echo esc_html($js_url) ?>" />
145
- <span class="dashicons dashicons-no item-remove" title="<?php _e('Remove', 'breeze') ?>"></span>
146
- </div>
147
- <?php endforeach; ?>
148
- <?php else : ?>
149
- <div class="breeze-input-group">
150
- <span class="sort-handle">
151
- <span class="dashicons dashicons-arrow-up moveUp"></span>
152
- <span class="dashicons dashicons-arrow-down moveDown"></span>
153
- </span>
154
- <input type="text" size="98"
155
- class="breeze-input-url"
156
- name="defer-js[]"
157
- id="defer-js"
158
- placeholder="<?php _e('Enter URL...', 'breeze') ?>"
159
- value="" />
160
- <span class="dashicons dashicons-no item-remove" title="<?php _e('Remove', 'breeze') ?>"></span>
161
- </div>
162
- <?php endif; ?>
163
- </div>
164
- <div style="margin: 10px 0">
165
- <button type="button" class="button add-url" id="add-defer-js">
166
- <?php _e('Add URL', 'breeze') ?>
167
- </button>
168
- </div>
169
- <div>
170
- <span class="breeze_tool_tip">
171
- <b>Note:&nbsp;</b>
172
- <?php _e('You should add the URL of original files as URL of minified files are not supported.', 'breeze') ?>
173
- </span>
174
- </div>
175
- </td>
176
- </tr>
177
- </table>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined( 'ABSPATH' ) or die;
3
+
4
+ $advanced = breeze_get_option( 'advanced_settings', true );
5
+
6
+ $excluded_css_check = true;
7
+ $excluded_js_check = true;
8
+ $excluded_css_check_extension = true;
9
+ $excluded_js_check_extension = true;
10
+ if ( isset( $advanced['breeze-exclude-css'] ) && ! empty( $advanced['breeze-exclude-css'] ) ) {
11
+ $excluded_css_check = breeze_validate_urls( $advanced['breeze-exclude-css'] );
12
+ if ( true === $excluded_css_check ) {
13
+ $excluded_css_check_extension = breeze_validate_the_right_extension( $advanced['breeze-exclude-css'], 'css' );
14
+ }
15
+ }
16
+
17
+ if ( isset( $advanced['breeze-exclude-js'] ) && ! empty( $advanced['breeze-exclude-js'] ) ) {
18
+ $excluded_js_check = breeze_validate_urls( $advanced['breeze-exclude-js'] );
19
+ if ( true === $excluded_js_check ) {
20
+ $excluded_js_check_extension = breeze_validate_the_right_extension( $advanced['breeze-exclude-js'], 'js' );
21
+ }
22
+ }
23
+ ?>
24
+ <table cellspacing="15">
25
+ <tr>
26
+ <td>
27
+ <label for="exclude-urls" class="breeze_tool_tip"><?php _e( 'Never Cache these URLs', 'breeze' ); ?></label>
28
+ </td>
29
+ <td>
30
+ <?php
31
+ $css_output = '';
32
+ if ( ! empty( $advanced['breeze-exclude-urls'] ) ) {
33
+ $output = implode( "\n", $advanced['breeze-exclude-urls'] );
34
+ $css_output = esc_textarea( $output );
35
+ }
36
+ ?>
37
+ <textarea cols="100" rows="7" id="exclude-urls" name="exclude-urls"><?php echo $css_output; ?></textarea>
38
+ <br/>
39
+ <span class="breeze_tool_tip"><b>Note:&nbsp;</b><?php _e( 'Add the URLs of the pages (one per line) you wish to exclude from the WordPress internal cache. To exclude URLs from the Varnish cache, please refer to this ', 'breeze' ); ?><a
40
+ href="https://support.cloudways.com/how-to-exclude-url-from-varnish/"
41
+ target="_blank"><?php _e( 'Knowledge Base', 'breeze' ); ?></a><?php _e( ' article.', 'breeze' ); ?> </span>
42
+ </td>
43
+ </tr>
44
+ <tr>
45
+ <td>
46
+ <label class="breeze_tool_tip"><?php _e( 'Group Files', 'breeze' ); ?></label>
47
+ </td>
48
+ <td>
49
+ <ul>
50
+ <li>
51
+ <input type="checkbox" name="group-css" id="group-css"
52
+ value="1" <?php checked( $advanced['breeze-group-css'], '1' ); ?>/>
53
+ <label class="breeze_tool_tip" for="group-css"><?php _e( 'CSS', 'breeze' ); ?></label>
54
+ </li>
55
+ <li>
56
+ <input type="checkbox" name="group-js" id="group-js"
57
+ value="1" <?php checked( $advanced['breeze-group-js'], '1' ); ?>/>
58
+ <label class="breeze_tool_tip" for="group-js"><?php _e( 'JS', 'breeze' ); ?></label>
59
+ </li>
60
+ <li>
61
+ <span class="breeze_tool_tip">
62
+ <b>Note:&nbsp;</b><?php _e( 'Group CSS and JS files to combine them into a single file. This will reduce the number of HTTP requests to your server.', 'breeze' ); ?><br>
63
+ <b><?php _e( 'Important: Enable Minification to use this option.', 'breeze' ); ?></b>
64
+ </span>
65
+ </li>
66
+ </ul>
67
+ </td>
68
+ </tr>
69
+ <tr>
70
+ <td>
71
+ <label for="exclude-css" class="breeze_tool_tip"><?php _e( 'Exclude CSS', 'breeze' ); ?></label>
72
+ </td>
73
+ <td>
74
+ <?php
75
+ $css_output = '';
76
+ if ( ! empty( $advanced['breeze-exclude-css'] ) ) {
77
+ $output = implode( "\n", $advanced['breeze-exclude-css'] );
78
+ $css_output = esc_textarea( $output );
79
+ }
80
+ ?>
81
+ <textarea cols="100" rows="7" id="exclude-css" name="exclude-css"><?php echo $css_output; ?></textarea>
82
+ <?php if ( false === $excluded_css_check_extension ) { ?>
83
+ <br/><span class="breeze_tool_tip"
84
+ style="color: #ff0000"><?php _e( 'One (or more) URL is incorrect. Please confirm that all URLs have the .css extension', 'breeze' ); ?></span>
85
+ <?php } ?>
86
+ <?php if ( false === $excluded_css_check ) { ?>
87
+ <br/><span class="breeze_tool_tip" style="color: #ff0000"><?php _e( 'One (or more) URL is invalid. Please check and correct the entry.', 'breeze' ); ?></span>
88
+ <?php } ?>
89
+ <br/>
90
+ <span class="breeze_tool_tip"><b>Note:&nbsp;</b><?php _e( 'Use this option to exclude CSS files from Minification and Grouping. Enter the URLs of CSS files on each line.', 'breeze' ); ?></span>
91
+ </td>
92
+ </tr>
93
+ <tr>
94
+ <td>
95
+ <label for="exclude-js" class="breeze_tool_tip"><?php _e( 'Exclude JS', 'breeze' ); ?></label>
96
+ </td>
97
+ <td>
98
+ <?php
99
+ $js_output = '';
100
+ if ( ! empty( $advanced['breeze-exclude-js'] ) ) {
101
+ $output = implode( "\n", $advanced['breeze-exclude-js'] );
102
+ $js_output = esc_textarea( $output );
103
+ }
104
+ ?>
105
+ <textarea cols="100" rows="7" id="exclude-js" name="exclude-js"><?php echo $js_output; ?></textarea>
106
+ <?php if ( false === $excluded_js_check_extension ) { ?>
107
+ <br/><span class="breeze_tool_tip"
108
+ style="color: #ff0000"><?php _e( 'One (or more) URL is incorrect. Please confirm that all URLs have the .js extension', 'breeze' ); ?></span>
109
+ <?php } ?>
110
+ <?php if ( false === $excluded_js_check ) { ?>
111
+ <br/><span class="breeze_tool_tip" style="color: #ff0000"><?php _e( 'One (or more) URL is invalid. Please check and correct the entry.', 'breeze' ); ?></span>
112
+ <?php } ?>
113
+ <br/>
114
+ <span class="breeze_tool_tip"><b>Note:&nbsp;</b><?php _e( 'Use this option to exclude JS files from Minification and Grouping. Enter the URLs of JS files on each line.', 'breeze' ); ?></span>
115
+ </td>
116
+ </tr>
117
+ <tr>
118
+ <td>
119
+ <label for="move-to-footer-js" class="breeze_tool_tip"><?php _e( 'Move JS files to footer', 'breeze' ); ?></label>
120
+ </td>
121
+ <td>
122
+ <div class="breeze-list-url">
123
+ <?php if ( ! empty( $advanced['breeze-move-to-footer-js'] ) ) : ?>
124
+ <?php foreach ( $advanced['breeze-move-to-footer-js'] as $js_url ) : ?>
125
+ <div class="breeze-input-group">
126
+ <span class="sort-handle">
127
+ <span class="dashicons dashicons-arrow-up moveUp"></span>
128
+ <span class="dashicons dashicons-arrow-down moveDown"></span>
129
+ </span>
130
+ <input type="text" size="98"
131
+ class="breeze-input-url"
132
+ name="move-to-footer-js[]"
133
+ placeholder="<?php _e( 'Enter URL...', 'breeze' ); ?>"
134
+ value="<?php echo esc_html( $js_url ); ?>"/>
135
+ <span class="dashicons dashicons-no item-remove" title="<?php _e( 'Remove', 'breeze' ); ?>"></span>
136
+ </div>
137
+ <?php endforeach; ?>
138
+ <?php else : ?>
139
+ <div class="breeze-input-group">
140
+ <span class="sort-handle">
141
+ <span class="dashicons dashicons-arrow-up moveUp"></span>
142
+ <span class="dashicons dashicons-arrow-down moveDown"></span>
143
+ </span>
144
+ <input type="text" size="98"
145
+ class="breeze-input-url"
146
+ id="move-to-footer-js"
147
+ name="move-to-footer-js[]"
148
+ placeholder="<?php _e( 'Enter URL...', 'breeze' ); ?>"
149
+ value=""/>
150
+ <span class="dashicons dashicons-no" title="<?php _e( 'Remove', 'breeze' ); ?>"></span>
151
+ </div>
152
+ <?php endif; ?>
153
+ </div>
154
+ <div style="margin: 10px 0">
155
+ <button type="button" class="button add-url" id="add-move-to-footer-js">
156
+ <?php _e( 'Add URL', 'breeze' ); ?>
157
+ </button>
158
+ </div>
159
+ <div>
160
+ <span class="breeze_tool_tip">
161
+ <b>Note:&nbsp;</b>
162
+ <?php _e( 'Enter the complete URLs of JS files to be moved to the footer during minification process.', 'breeze' ); ?>
163
+ </span>
164
+ <span class="breeze_tool_tip">
165
+ <?php _e( 'You should add the URL of original files as URL of minified files are not supported.', 'breeze' ); ?>
166
+ </span>
167
+ </div>
168
+ </td>
169
+ </tr>
170
+ <tr>
171
+ <td>
172
+ <label for="defer-js" class="breeze_tool_tip"><?php _e( 'JS files with deferred loading', 'breeze' ); ?></label>
173
+ </td>
174
+ <td>
175
+ <div class="breeze-list-url">
176
+ <?php if ( ! empty( $advanced['breeze-defer-js'] ) ) : ?>
177
+ <?php foreach ( $advanced['breeze-defer-js'] as $js_url ) : ?>
178
+ <div class="breeze-input-group">
179
+ <span class="sort-handle">
180
+ <span class="dashicons dashicons-arrow-up moveUp"></span>
181
+ <span class="dashicons dashicons-arrow-down moveDown"></span>
182
+ </span>
183
+ <input type="text" size="98"
184
+ class="breeze-input-url"
185
+ name="defer-js[]"
186
+ placeholder="<?php _e( 'Enter URL...', 'breeze' ); ?>"
187
+ value="<?php echo esc_html( $js_url ); ?>"/>
188
+ <span class="dashicons dashicons-no item-remove" title="<?php _e( 'Remove', 'breeze' ); ?>"></span>
189
+ </div>
190
+ <?php endforeach; ?>
191
+ <?php else : ?>
192
+ <div class="breeze-input-group">
193
+ <span class="sort-handle">
194
+ <span class="dashicons dashicons-arrow-up moveUp"></span>
195
+ <span class="dashicons dashicons-arrow-down moveDown"></span>
196
+ </span>
197
+ <input type="text" size="98"
198
+ class="breeze-input-url"
199
+ name="defer-js[]"
200
+ id="defer-js"
201
+ placeholder="<?php _e( 'Enter URL...', 'breeze' ); ?>"
202
+ value=""/>
203
+ <span class="dashicons dashicons-no item-remove" title="<?php _e( 'Remove', 'breeze' ); ?>"></span>
204
+ </div>
205
+ <?php endif; ?>
206
+ </div>
207
+ <div style="margin: 10px 0">
208
+ <button type="button" class="button add-url" id="add-defer-js">
209
+ <?php _e( 'Add URL', 'breeze' ); ?>
210
+ </button>
211
+ </div>
212
+ <div>
213
+ <span class="breeze_tool_tip">
214
+ <b>Note:&nbsp;</b>
215
+ <?php _e( 'You should add the URL of original files as URL of minified files are not supported.', 'breeze' ); ?>
216
+ </span>
217
+ </div>
218
+ </td>
219
+ </tr>
220
+ </table>