Breeze – WordPress Cache Plugin - Version 1.1.10

Version Description

  • Fix: Apply deferred loading at individual file.
  • Fix: exclude feed url generated by plugin Facebook for WooCommerce.
  • Fix: purge site cache in subfolder.
  • Fix: Inventory stock now updated at the Cart page.
  • Fix: Improved Support for the new version of the WooCommerce Booking Calendar plugin.
  • Add: Compatible with EDD and cartflow plugins.
  • Add: pages include shortcode has been exclude by Breeze.
Download this release

Release Info

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

Code changes from version 1.1.9 to 1.1.10

Files changed (38) hide show
  1. breeze.php +386 -219
  2. inc/breeze-admin.php +1 -3
  3. inc/breeze-configuration.php +754 -753
  4. inc/cache/Mobile-Detect-2.8.25/Mobile_Detect.php +1425 -1460
  5. inc/cache/Mobile-Detect-2.8.25/export/exportToJSON.php +66 -67
  6. inc/cache/Mobile-Detect-2.8.25/namespaced/Detection/MobileDetect.php +22 -22
  7. inc/cache/config-cache.php +489 -347
  8. inc/cache/ecommerce-cache.php +639 -188
  9. inc/cache/execute-cache.php +498 -413
  10. inc/cache/purge-cache.php +175 -173
  11. inc/cache/purge-per-time.php +120 -121
  12. inc/cache/purge-varnish.php +4 -5
  13. inc/cdn-integration/breeze-cdn-integration.php +62 -62
  14. inc/cdn-integration/breeze-cdn-rewrite.php +145 -145
  15. inc/class-breeze-woocommerce-product-cache.php +62 -0
  16. inc/class-exclude-pages-by-shortcode.php +11 -11
  17. inc/functions.php +2 -4
  18. inc/helpers.php +120 -2
  19. inc/minification/breeze-js-deferred-loading.php +110 -9
  20. inc/minification/breeze-minification-base.php +387 -394
  21. inc/minification/breeze-minification-cache.php +357 -368
  22. inc/minification/breeze-minification-html.php +120 -120
  23. inc/minification/breeze-minification-scripts.php +88 -50
  24. inc/minification/breeze-minification-styles.php +31 -33
  25. inc/minification/breeze-minify-main.php +390 -382
  26. inc/minification/config/default.php +67 -64
  27. inc/minification/config/delayed.php +87 -85
  28. inc/minification/config/minificationFontRegex.php +8 -8
  29. inc/minification/minify/minify-css-compressor.php +276 -250
  30. inc/minification/minify/minify-html.php +270 -268
  31. readme.txt +11 -1
  32. views/breeze-setting-views.php +133 -133
  33. views/tabs/advanced.php +2 -2
  34. views/tabs/basic.php +170 -170
  35. views/tabs/cdn.php +85 -85
  36. views/tabs/database.php +112 -107
  37. views/tabs/faq.php +158 -158
  38. views/tabs/varnish.php +46 -46
breeze.php CHANGED
@@ -1,219 +1,386 @@
1
- <?php
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.9
6
- * Text Domain: breeze
7
- * Domain Path: /languages
8
- * Author: Cloudways
9
- * Author URI: https://www.cloudways.com
10
- * License: GPL2
11
- * Network: true
12
- */
13
-
14
- /**
15
- * @copyright 2017 Cloudways https://www.cloudways.com
16
- *
17
- * This plugin is inspired from WP Speed of Light by JoomUnited.
18
- *
19
- * This program is free software; you can redistribute it and/or modify
20
- * it under the terms of the GNU General Public License as published by
21
- * the Free Software Foundation; either version 2 of the License, or
22
- * (at your option) any later version.
23
- *
24
- * This program is distributed in the hope that it will be useful,
25
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
26
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27
- * GNU General Public License for more details.
28
- *
29
- * You should have received a copy of the GNU General Public License
30
- * along with this program; if not, write to the Free Software
31
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
32
- */
33
-
34
- defined( 'ABSPATH' ) || die( 'No direct script access allowed!' );
35
-
36
- if ( ! defined( 'BREEZE_PLUGIN_DIR' ) ) {
37
- define( 'BREEZE_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
38
- }
39
- if ( ! defined( 'BREEZE_VERSION' ) ) {
40
- define( 'BREEZE_VERSION', '1.1.9' );
41
- }
42
- if ( ! defined( 'BREEZE_SITEURL' ) ) {
43
- define( 'BREEZE_SITEURL', get_site_url() );
44
- }
45
- if ( ! defined( 'BREEZE_MINIFICATION_CACHE' ) ) {
46
- define( 'BREEZE_MINIFICATION_CACHE', WP_CONTENT_DIR . '/cache/breeze-minification/' );
47
- }
48
- if ( ! defined( 'BREEZE_CACHEFILE_PREFIX' ) ) {
49
- define( 'BREEZE_CACHEFILE_PREFIX', 'breeze_' );
50
- }
51
- if ( ! defined( 'BREEZE_CACHE_CHILD_DIR' ) ) {
52
- define( 'BREEZE_CACHE_CHILD_DIR', '/cache/breeze-minification/' );
53
- }
54
- if ( ! defined( 'BREEZE_WP_CONTENT_NAME' ) ) {
55
- define( 'BREEZE_WP_CONTENT_NAME', '/' . wp_basename( WP_CONTENT_DIR ) );
56
- }
57
- if ( ! defined( 'BREEZE_BASENAME' ) ) {
58
- define( 'BREEZE_BASENAME', plugin_basename( __FILE__ ) );
59
- }
60
-
61
- define( 'BREEZE_CACHE_DELAY', true );
62
- define( 'BREEZE_CACHE_NOGZIP', true );
63
- define( 'BREEZE_ROOT_DIR', str_replace( BREEZE_WP_CONTENT_NAME, '', WP_CONTENT_DIR ) );
64
-
65
- // Compatibility checks
66
- require_once BREEZE_PLUGIN_DIR . 'inc/plugin-incompatibility/class-breeze-incompatibility-plugins.php';
67
-
68
- // Helper functions.
69
- require_once BREEZE_PLUGIN_DIR . 'inc/helpers.php';
70
- require_once BREEZE_PLUGIN_DIR . 'inc/functions.php';
71
-
72
- //action to purge cache
73
- require_once( BREEZE_PLUGIN_DIR . 'inc/cache/purge-varnish.php' );
74
- require_once( BREEZE_PLUGIN_DIR . 'inc/cache/purge-cache.php' );
75
- require_once( BREEZE_PLUGIN_DIR . 'inc/cache/purge-per-time.php' );
76
- // Handle post exclude if shortcode.
77
- require_once( BREEZE_PLUGIN_DIR . 'inc/class-exclude-pages-by-shortcode.php' );
78
-
79
- // Activate plugin hook
80
- register_activation_hook( __FILE__, array( 'Breeze_Admin', 'plugin_active_hook' ) );
81
- //Deactivate plugin hook
82
- register_deactivation_hook( __FILE__, array( 'Breeze_Admin', 'plugin_deactive_hook' ) );
83
-
84
- require_once( BREEZE_PLUGIN_DIR . 'inc/breeze-admin.php' );
85
-
86
- if ( is_admin() || 'cli' === php_sapi_name() ) {
87
-
88
- require_once( BREEZE_PLUGIN_DIR . 'inc/breeze-configuration.php' );
89
- //config to cache
90
- require_once( BREEZE_PLUGIN_DIR . 'inc/cache/config-cache.php' );
91
-
92
- //cache when ecommerce installed
93
- require_once( BREEZE_PLUGIN_DIR . 'inc/cache/ecommerce-cache.php' );
94
- add_action( 'init', function () {
95
- new Breeze_Ecommerce_Cache();
96
- }, 0 );
97
-
98
- } else {
99
- $cdn_conf = breeze_get_option( 'cdn_integration' );
100
- $basic_conf = breeze_get_option( 'basic_settings' );
101
- $config_advanced = breeze_get_option( 'advanced_settings' );
102
-
103
- if ( ! empty( $cdn_conf['cdn-active'] )
104
- || ! empty( $basic_conf['breeze-minify-js'] )
105
- || ! empty( $basic_conf['breeze-minify-css'] )
106
- || ! empty( $basic_conf['breeze-minify-html'] )
107
- || ! empty( $config_advanced['breeze-defer-js'] ) ) {
108
- // Call back ob start
109
- ob_start( 'breeze_ob_start_callback' );
110
- }
111
- }
112
-
113
- // Call back ob start - stack
114
- function breeze_ob_start_callback( $buffer ) {
115
- $conf = breeze_get_option( 'cdn_integration' );
116
- // Get buffer from minify
117
- $buffer = apply_filters( 'breeze_minify_content_return', $buffer );
118
-
119
- if ( ! empty( $conf ) || ! empty( $conf['cdn-active'] ) ) {
120
- // Get buffer after remove query strings
121
- $buffer = apply_filters( 'breeze_cdn_content_return', $buffer );
122
- }
123
-
124
- // Return content
125
- return $buffer;
126
- }
127
-
128
- // Minify
129
-
130
- require_once( BREEZE_PLUGIN_DIR . 'inc/minification/breeze-minify-main.php' );
131
- require_once( BREEZE_PLUGIN_DIR . 'inc/minification/breeze-minification-cache.php' );
132
- add_action( 'init', function () {
133
- new Breeze_Minify();
134
-
135
- }, 0 );
136
- // CDN Integration
137
- if ( ! class_exists( 'Breeze_CDN_Integration' ) ) {
138
- require_once( BREEZE_PLUGIN_DIR . 'inc/cdn-integration/breeze-cdn-integration.php' );
139
- require_once( BREEZE_PLUGIN_DIR . 'inc/cdn-integration/breeze-cdn-rewrite.php' );
140
- add_action( 'init', function () {
141
- new Breeze_CDN_Integration();
142
- }, 0 );
143
- }
144
-
145
-
146
- /**
147
- * This function will update htaccess files after the plugin update is done.
148
- *
149
- * This function runs when WordPress completes its upgrade process.
150
- * It iterates through each plugin updated to see if ours is included.
151
- *
152
- * The plugin must be active while updating, otherwise this will do nothing.
153
- *
154
- * @see https://codex.wordpress.org/Plugin_API/Action_Reference/upgrader_process_complete
155
- * @since 1.1.3
156
- *
157
- * @param array $upgrader_object
158
- * @param array $options
159
- */
160
- function breeze_after_plugin_update_done( $upgrader_object, $options ) {
161
- // If an update has taken place and the updated type is plugins and the plugins element exists.
162
- if ( $options['action'] == 'update' && $options['type'] == 'plugin' && isset( $options['plugins'] ) ) {
163
- // Iterate through the plugins being updated and check if ours is there
164
- foreach ( $options['plugins'] as $plugin ) {
165
- if ( $plugin == BREEZE_BASENAME ) {
166
- // Add a new option to inform the install that a new version was installed.
167
- add_option( 'breeze_new_update', 'yes', '', false );
168
- }
169
- }
170
- }
171
- }
172
-
173
- add_action( 'upgrader_process_complete', 'breeze_after_plugin_update_done', 10, 2 );
174
-
175
- function breeze_check_for_new_version() {
176
- if ( ! empty( get_option( 'breeze_new_update', '' ) ) ) {
177
- if ( class_exists( 'Breeze_Configuration' ) && method_exists( 'Breeze_Configuration', 'update_htaccess' ) ) {
178
- Breeze_Configuration::update_htaccess();
179
- }
180
- delete_option( 'breeze_new_update' );
181
- }
182
- }
183
-
184
- add_action( 'init', 'breeze_check_for_new_version', 99 );
185
-
186
- // @TODO: remove debug code.
187
- if ( isset( $_GET['settings_debug'] ) ) {
188
- $settings = array(
189
- 'basic_settings',
190
- 'advanced_settings',
191
- 'cdn_integration',
192
- 'varnish_cache',
193
- );
194
-
195
- echo '<h1>Is multisite: ' . ( is_multisite() ? 'YES' : 'NO' ) . '</h1>';
196
-
197
- if ( is_multisite() ) {
198
- $inherit_option = get_option( 'breeze_inherit_settings' );
199
- $inherit = true;
200
-
201
- if ( ! is_network_admin() && '0' === $inherit_option ) {
202
- $inherit = false;
203
- }
204
-
205
- echo '<h1>Using global settings: ' . ( $inherit ? 'YES' : 'NO' ) . '</h1>';
206
- }
207
-
208
- foreach ( $settings as $setting ) {
209
- echo '<h2>' . $setting . '</h2>';
210
- echo '<pre>';
211
- print_r( breeze_get_option( $setting ) );
212
- echo '</pre>';
213
- }
214
-
215
- echo '<h2>Gzip enabled: ' . ( getenv( 'BREEZE_GZIP_ON' ) ? 'YES' : 'NO' ) . '</h2>';
216
- echo '<h2>Browser cache enabled: ' . ( getenv( 'BREEZE_BROWSER_CACHE_ON' ) ? 'YES' : 'NO' ) . '</h2>';
217
-
218
- exit;
219
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
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.10
6
+ * Text Domain: breeze
7
+ * Domain Path: /languages
8
+ * Author: Cloudways
9
+ * Author URI: https://www.cloudways.com
10
+ * License: GPL2
11
+ * Network: true
12
+ */
13
+
14
+ /**
15
+ * @copyright 2017 Cloudways https://www.cloudways.com
16
+ *
17
+ * This plugin is inspired from WP Speed of Light by JoomUnited.
18
+ *
19
+ * This program is free software; you can redistribute it and/or modify
20
+ * it under the terms of the GNU General Public License as published by
21
+ * the Free Software Foundation; either version 2 of the License, or
22
+ * (at your option) any later version.
23
+ *
24
+ * This program is distributed in the hope that it will be useful,
25
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
26
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27
+ * GNU General Public License for more details.
28
+ *
29
+ * You should have received a copy of the GNU General Public License
30
+ * along with this program; if not, write to the Free Software
31
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
32
+ */
33
+
34
+ defined( 'ABSPATH' ) || die( 'No direct script access allowed!' );
35
+
36
+ if ( ! defined( 'BREEZE_PLUGIN_DIR' ) ) {
37
+ define( 'BREEZE_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
38
+ }
39
+ if ( ! defined( 'BREEZE_VERSION' ) ) {
40
+ define( 'BREEZE_VERSION', '1.1.10' );
41
+ }
42
+ if ( ! defined( 'BREEZE_SITEURL' ) ) {
43
+ define( 'BREEZE_SITEURL', get_site_url() );
44
+ }
45
+ if ( ! defined( 'BREEZE_MINIFICATION_CACHE' ) ) {
46
+ define( 'BREEZE_MINIFICATION_CACHE', WP_CONTENT_DIR . '/cache/breeze-minification/' );
47
+ }
48
+ if ( ! defined( 'BREEZE_CACHEFILE_PREFIX' ) ) {
49
+ define( 'BREEZE_CACHEFILE_PREFIX', 'breeze_' );
50
+ }
51
+ if ( ! defined( 'BREEZE_CACHE_CHILD_DIR' ) ) {
52
+ define( 'BREEZE_CACHE_CHILD_DIR', '/cache/breeze-minification/' );
53
+ }
54
+ if ( ! defined( 'BREEZE_WP_CONTENT_NAME' ) ) {
55
+ define( 'BREEZE_WP_CONTENT_NAME', '/' . wp_basename( WP_CONTENT_DIR ) );
56
+ }
57
+ if ( ! defined( 'BREEZE_BASENAME' ) ) {
58
+ define( 'BREEZE_BASENAME', plugin_basename( __FILE__ ) );
59
+ }
60
+
61
+ define( 'BREEZE_CACHE_DELAY', true );
62
+ define( 'BREEZE_CACHE_NOGZIP', true );
63
+ define( 'BREEZE_ROOT_DIR', str_replace( BREEZE_WP_CONTENT_NAME, '', WP_CONTENT_DIR ) );
64
+
65
+ // Compatibility checks
66
+ require_once BREEZE_PLUGIN_DIR . 'inc/plugin-incompatibility/class-breeze-incompatibility-plugins.php';
67
+
68
+ // Helper functions.
69
+ require_once BREEZE_PLUGIN_DIR . 'inc/helpers.php';
70
+ require_once BREEZE_PLUGIN_DIR . 'inc/functions.php';
71
+
72
+ //action to purge cache
73
+ require_once( BREEZE_PLUGIN_DIR . 'inc/cache/purge-varnish.php' );
74
+ require_once( BREEZE_PLUGIN_DIR . 'inc/cache/purge-cache.php' );
75
+ require_once( BREEZE_PLUGIN_DIR . 'inc/cache/purge-per-time.php' );
76
+ // Handle post exclude if shortcode.
77
+ require_once( BREEZE_PLUGIN_DIR . 'inc/class-exclude-pages-by-shortcode.php' );
78
+
79
+ // Activate plugin hook
80
+ register_activation_hook( __FILE__, array( 'Breeze_Admin', 'plugin_active_hook' ) );
81
+ //Deactivate plugin hook
82
+ register_deactivation_hook( __FILE__, array( 'Breeze_Admin', 'plugin_deactive_hook' ) );
83
+
84
+ require_once( BREEZE_PLUGIN_DIR . 'inc/breeze-admin.php' );
85
+
86
+ if ( is_admin() || 'cli' === php_sapi_name() ) {
87
+
88
+ require_once( BREEZE_PLUGIN_DIR . 'inc/breeze-configuration.php' );
89
+ //config to cache
90
+ require_once( BREEZE_PLUGIN_DIR . 'inc/cache/config-cache.php' );
91
+
92
+ //cache when ecommerce installed
93
+ require_once( BREEZE_PLUGIN_DIR . 'inc/cache/ecommerce-cache.php' );
94
+ add_action(
95
+ 'init',
96
+ function () {
97
+ new Breeze_Ecommerce_Cache();
98
+ },
99
+ 0
100
+ );
101
+
102
+ } else {
103
+ $cdn_conf = breeze_get_option( 'cdn_integration' );
104
+ $basic_conf = breeze_get_option( 'basic_settings' );
105
+ $config_advanced = breeze_get_option( 'advanced_settings' );
106
+
107
+ if ( ! empty( $cdn_conf['cdn-active'] )
108
+ || ! empty( $basic_conf['breeze-minify-js'] )
109
+ || ! empty( $basic_conf['breeze-minify-css'] )
110
+ || ! empty( $basic_conf['breeze-minify-html'] )
111
+ || ! empty( $config_advanced['breeze-defer-js'] )
112
+ || ! empty( $config_advanced['breeze-move-to-footer-js'] )
113
+ ) {
114
+ // Call back ob start
115
+ ob_start( 'breeze_ob_start_callback' );
116
+ }
117
+ }
118
+
119
+ // Call back ob start - stack
120
+ function breeze_ob_start_callback( $buffer ) {
121
+ $conf = breeze_get_option( 'cdn_integration' );
122
+ // Get buffer from minify
123
+ $buffer = apply_filters( 'breeze_minify_content_return', $buffer );
124
+
125
+ if ( ! empty( $conf ) || ! empty( $conf['cdn-active'] ) ) {
126
+ // Get buffer after remove query strings
127
+ $buffer = apply_filters( 'breeze_cdn_content_return', $buffer );
128
+ }
129
+
130
+ // Return content
131
+ return $buffer;
132
+ }
133
+
134
+ // Minify
135
+
136
+ require_once( BREEZE_PLUGIN_DIR . 'inc/minification/breeze-minify-main.php' );
137
+ require_once( BREEZE_PLUGIN_DIR . 'inc/minification/breeze-minification-cache.php' );
138
+ add_action(
139
+ 'init',
140
+ function () {
141
+ new Breeze_Minify();
142
+
143
+ },
144
+ 0
145
+ );
146
+ // CDN Integration
147
+ if ( ! class_exists( 'Breeze_CDN_Integration' ) ) {
148
+ require_once( BREEZE_PLUGIN_DIR . 'inc/cdn-integration/breeze-cdn-integration.php' );
149
+ require_once( BREEZE_PLUGIN_DIR . 'inc/cdn-integration/breeze-cdn-rewrite.php' );
150
+ add_action(
151
+ 'init',
152
+ function () {
153
+ new Breeze_CDN_Integration();
154
+ },
155
+ 0
156
+ );
157
+ }
158
+
159
+ // Refresh cache for ordered products.
160
+ require_once BREEZE_PLUGIN_DIR . 'inc/class-breeze-woocommerce-product-cache.php';
161
+ /**
162
+ * This function will update htaccess files after the plugin update is done.
163
+ *
164
+ * This function runs when WordPress completes its upgrade process.
165
+ * It iterates through each plugin updated to see if ours is included.
166
+ *
167
+ * The plugin must be active while updating, otherwise this will do nothing.
168
+ *
169
+ * @see https://codex.wordpress.org/Plugin_API/Action_Reference/upgrader_process_complete
170
+ * @since 1.1.3
171
+ *
172
+ * @param array $upgrader_object
173
+ * @param array $options
174
+ */
175
+ function breeze_after_plugin_update_done( $upgrader_object, $options ) {
176
+ // If an update has taken place and the updated type is plugins and the plugins element exists.
177
+ if ( $options['action'] == 'update' && $options['type'] == 'plugin' && isset( $options['plugins'] ) ) {
178
+ // Iterate through the plugins being updated and check if ours is there
179
+ foreach ( $options['plugins'] as $plugin ) {
180
+ if ( $plugin == BREEZE_BASENAME ) {
181
+ // If the install is multi-site, we will add the option for all the blogs.
182
+ if ( is_multisite() ) {
183
+ $blogs = get_sites();
184
+ if ( ! empty( $blogs ) ) {
185
+ foreach ( $blogs as $blog_data ) {
186
+ $blog_id = $blog_data->blog_id;
187
+ switch_to_blog( $blog_id );
188
+ // Add the option for each blog.
189
+ // The visit on any blog will trigger the update to happen.
190
+ add_option( 'breeze_new_update', 'yes', '', false );
191
+
192
+ restore_current_blog();
193
+ }
194
+ }
195
+ } else {
196
+ // Add a new option to inform the install that a new version was installed.
197
+ add_option( 'breeze_new_update', 'yes', '', false );
198
+ }
199
+ }
200
+ }
201
+ }
202
+ }
203
+
204
+ add_action( 'upgrader_process_complete', 'breeze_after_plugin_update_done', 10, 2 );
205
+
206
+ /**
207
+ * This function is checking on init if there is a need to update htaccess.
208
+ */
209
+ function breeze_check_for_new_version() {
210
+ // When permalinks are reset, we also reset the config files.
211
+ if ( isset( $_POST['permalink_structure'] ) || isset( $_POST['category_base'] ) ) {
212
+ check_admin_referer( 'update-permalink' );
213
+ // If the WP install is multi-site
214
+
215
+ global $wp_filesystem;
216
+ if ( empty( $wp_filesystem ) ) {
217
+ require_once( ABSPATH . '/wp-admin/includes/file.php' );
218
+ WP_Filesystem();
219
+ }
220
+
221
+ // import these file in front-end when required.
222
+ if ( ! class_exists( 'Breeze_Ecommerce_Cache' ) ) {
223
+ //cache when ecommerce installed
224
+ require_once( BREEZE_PLUGIN_DIR . 'inc/cache/ecommerce-cache.php' );
225
+ }
226
+
227
+ // import these file in front-end when required.
228
+ if ( ! class_exists( 'Breeze_ConfigCache' ) ) {
229
+ //config to cache
230
+ require_once( BREEZE_PLUGIN_DIR . 'inc/cache/config-cache.php' );
231
+ }
232
+
233
+ if ( is_multisite() ) {
234
+ // For multi-site we need to also reset the root config-file.
235
+ Breeze_ConfigCache::factory()->write_config_cache( true );
236
+
237
+ $blogs = get_sites();
238
+ if ( ! empty( $blogs ) ) {
239
+ foreach ( $blogs as $blog_data ) {
240
+ $blog_id = $blog_data->blog_id;
241
+ switch_to_blog( $blog_id );
242
+
243
+ // if the settings are inherited, then we do not need to refresh the config file.
244
+ $inherit_option = get_option( 'breeze_inherit_settings' );
245
+ $inherit_option = filter_var( $inherit_option, FILTER_VALIDATE_BOOLEAN );
246
+
247
+ // If the settings are not inherited from parent blog, then refresh the config file.
248
+ if ( false === $inherit_option ) {
249
+ // Refresh breeze-cache.php file
250
+ Breeze_ConfigCache::factory()->write_config_cache();
251
+ }
252
+
253
+ restore_current_blog();
254
+ }
255
+ }
256
+ } else {
257
+ // For single site.
258
+ // Refresh breeze-cache.php file
259
+ Breeze_ConfigCache::factory()->write_config_cache();
260
+ }
261
+ }
262
+
263
+ // This process can also be started by Wp-CLI.
264
+ if ( ! empty( get_option( 'breeze_new_update', '' ) ) ) {
265
+ // This needs to happen only once.
266
+ if ( class_exists( 'Breeze_Configuration' ) && method_exists( 'Breeze_Configuration', 'update_htaccess' ) ) {
267
+ Breeze_Configuration::update_htaccess();
268
+
269
+ }
270
+
271
+ // import these file in front-end when required.
272
+ if ( ! class_exists( 'Breeze_Ecommerce_Cache' ) ) {
273
+ //cache when ecommerce installed
274
+ require_once( BREEZE_PLUGIN_DIR . 'inc/cache/ecommerce-cache.php' );
275
+ }
276
+
277
+ // import these file in front-end when required.
278
+ if ( ! class_exists( 'Breeze_ConfigCache' ) ) {
279
+ //config to cache
280
+ require_once( BREEZE_PLUGIN_DIR . 'inc/cache/config-cache.php' );
281
+ }
282
+
283
+ // If the WP install is multi-site
284
+ if ( is_multisite() ) {
285
+ // For multi-site we need to also reset the root config-file.
286
+ Breeze_ConfigCache::factory()->write_config_cache( true );
287
+
288
+ $blogs = get_sites();
289
+ if ( ! empty( $blogs ) ) {
290
+ foreach ( $blogs as $blog_data ) {
291
+ $blog_id = $blog_data->blog_id;
292
+ switch_to_blog( $blog_id );
293
+
294
+ // if the settings are inherited, then we do not need to refresh the config file.
295
+ $inherit_option = get_option( 'breeze_inherit_settings' );
296
+ $inherit_option = filter_var( $inherit_option, FILTER_VALIDATE_BOOLEAN );
297
+
298
+ // If the settings are not inherited from parent blog, then refresh the config file.
299
+ if ( false === $inherit_option ) {
300
+ // Refresh breeze-cache.php file
301
+ Breeze_ConfigCache::factory()->write_config_cache();
302
+ }
303
+
304
+ // Remove the option from all the blogs, meaning each one of them was already updated.
305
+ delete_option( 'breeze_new_update' );
306
+
307
+ restore_current_blog();
308
+ }
309
+ }
310
+ } else {
311
+ // For single site.
312
+
313
+ // Refresh breeze-cache.php file
314
+ Breeze_ConfigCache::factory()->write_config_cache();
315
+
316
+ delete_option( 'breeze_new_update' );
317
+ }
318
+ }
319
+ }
320
+
321
+ add_action( 'init', 'breeze_check_for_new_version', 99 );
322
+
323
+
324
+ add_action( 'wp_login', 'refresh_config_files', 10, 2 );
325
+
326
+ /**
327
+ * Handles the config file reset.
328
+ *
329
+ * @param string $user_login $user->user_login
330
+ * @param object $user WP_User
331
+ *
332
+ * @since 1.1.5
333
+ */
334
+ function refresh_config_files( $user_login, $user ) {
335
+ if ( in_array( 'administrator', (array) $user->roles, true ) ) {
336
+ //The user has the "administrator" role
337
+ global $wp_filesystem;
338
+ if ( empty( $wp_filesystem ) ) {
339
+ require_once( ABSPATH . '/wp-admin/includes/file.php' );
340
+ WP_Filesystem();
341
+ }
342
+ // import these file in front-end when required.
343
+ if ( ! class_exists( 'Breeze_Ecommerce_Cache' ) ) {
344
+ //cache when ecommerce installed
345
+ require_once( BREEZE_PLUGIN_DIR . 'inc/cache/ecommerce-cache.php' );
346
+ }
347
+
348
+ // import these file in front-end when required.
349
+ if ( ! class_exists( 'Breeze_ConfigCache' ) ) {
350
+ //config to cache
351
+ require_once( BREEZE_PLUGIN_DIR . 'inc/cache/config-cache.php' );
352
+ }
353
+ if ( is_multisite() ) {
354
+ $blogs = get_sites();
355
+ // For multi-site we need to also reset the root config-file.
356
+ Breeze_ConfigCache::factory()->write_config_cache( true );
357
+
358
+ if ( ! empty( $blogs ) ) {
359
+ foreach ( $blogs as $blog_data ) {
360
+ $blog_id = $blog_data->blog_id;
361
+ switch_to_blog( $blog_id );
362
+
363
+ // if the settings are inherited, then we do not need to refresh the config file.
364
+ $inherit_option = get_option( 'breeze_inherit_settings' );
365
+ $inherit_option = filter_var( $inherit_option, FILTER_VALIDATE_BOOLEAN );
366
+ // If the settings are not inherited from parent blog, then refresh the config file.
367
+ if ( false === $inherit_option ) {
368
+ // Refresh breeze-cache.php file
369
+ Breeze_ConfigCache::factory()->write_config_cache();
370
+ }
371
+ restore_current_blog();
372
+ }
373
+ }
374
+ } else {
375
+ $current_file = WP_CONTENT_DIR . '/breeze-config/breeze-config.php';
376
+ if ( file_exists( $current_file ) ) {
377
+ $current_data = include $current_file; //phpcs:ignore
378
+ if ( mb_strtolower( $current_data['homepage'] ) !== get_site_url() ) {
379
+ // For single site.
380
+ // Refresh breeze-cache.php file
381
+ Breeze_ConfigCache::factory()->write_config_cache();
382
+ }
383
+ }
384
+ }
385
+ }
386
+ }
inc/breeze-admin.php CHANGED
@@ -194,14 +194,13 @@ class Breeze_Admin {
194
  $current_params = $_SERVER['QUERY_STRING'];
195
 
196
  if ( is_multisite() && ! is_subdomain_install() ) {
197
- $blog_details = get_blog_details();
198
  $current_host .= rtrim( $blog_details->path, '/' );
199
  }
200
 
201
  $current_screen_url = $current_protocol . '://' . $current_host . $current_script . '?' . $current_params;
202
  $current_screen_url = remove_query_arg( array( 'breeze_purge', '_wpnonce' ), $current_screen_url );
203
 
204
-
205
  // add purge all item
206
  $args = array(
207
  'id' => 'breeze-purge-all',
@@ -465,7 +464,6 @@ class Breeze_Admin {
465
  * Clear all cache action.
466
  */
467
  public function breeze_clear_all_cache() {
468
-
469
  //delete minify
470
  Breeze_MinificationCache::clear_minification();
471
  //clear normal cache
194
  $current_params = $_SERVER['QUERY_STRING'];
195
 
196
  if ( is_multisite() && ! is_subdomain_install() ) {
197
+ $blog_details = get_blog_details();
198
  $current_host .= rtrim( $blog_details->path, '/' );
199
  }
200
 
201
  $current_screen_url = $current_protocol . '://' . $current_host . $current_script . '?' . $current_params;
202
  $current_screen_url = remove_query_arg( array( 'breeze_purge', '_wpnonce' ), $current_screen_url );
203
 
 
204
  // add purge all item
205
  $args = array(
206
  'id' => 'breeze-purge-all',
464
  * Clear all cache action.
465
  */
466
  public function breeze_clear_all_cache() {
 
467
  //delete minify
468
  Breeze_MinificationCache::clear_minification();
469
  //clear normal cache
inc/breeze-configuration.php CHANGED
@@ -1,753 +1,754 @@
1
- <?php
2
- /**
3
- * @copyright 2017 Cloudways https://www.cloudways.com
4
- *
5
- * This plugin is inspired from WP Speed of Light by JoomUnited.
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_Configuration{
24
- public function __construct()
25
- {
26
- global $breeze_network_subsite_settings;
27
- $breeze_network_subsite_settings = false;
28
- add_action( 'load-settings_page_breeze', array($this,'afterLoadConfigPage') );
29
- }
30
-
31
-
32
- /*
33
- * function to save settings
34
- */
35
- public function afterLoadConfigPage() {
36
- // Per-site settings (multisite inheriting)
37
- if (
38
- is_multisite() &&
39
- isset( $_REQUEST['inherit-settings'] ) &&
40
- isset( $_POST['breeze_inherit_settings_nonce'] ) &&
41
- wp_verify_nonce( $_POST['breeze_inherit_settings_nonce'], 'breeze_inherit_settings' )
42
- ) {
43
- $inherit_settings = ( 1 == $_REQUEST['inherit-settings'] ? '1' : '0' );
44
- update_option( 'breeze_inherit_settings', $inherit_settings );
45
-
46
- if ( ! isset( $_REQUEST['breeze_basic_action'], $_REQUEST['breeze_advanced_action'] ) ) {
47
- WP_Filesystem();
48
- Breeze_ConfigCache::factory()->write_config_cache();
49
- }
50
- }
51
-
52
- // Basic options tab
53
- if (isset($_REQUEST['breeze_basic_action']) && $_REQUEST['breeze_basic_action'] == 'breeze_basic_settings') {
54
- if (isset($_POST['breeze_settings_basic_nonce']) && wp_verify_nonce($_POST['breeze_settings_basic_nonce'], 'breeze_settings_basic')) {
55
- WP_Filesystem();
56
-
57
- $basic = array(
58
- 'breeze-active' =>(isset($_POST['cache-system']) ? '1' : '0'),
59
- 'breeze-ttl' => (int)$_POST['cache-ttl'],
60
- 'breeze-minify-html' => (isset($_POST['minification-html']) ? '1' : '0'),
61
- 'breeze-minify-css' => (isset($_POST['minification-css']) ? '1' : '0'),
62
- 'breeze-minify-js' => (isset($_POST['minification-js']) ? '1' : '0'),
63
- 'breeze-gzip-compression' => (isset($_POST['gzip-compression']) ? '1' : '0'),
64
- 'breeze-browser-cache' => (isset($_POST['browser-cache']) ? '1' : '0'),
65
- 'breeze-desktop-cache' => (int)$_POST['desktop-cache'],
66
- 'breeze-mobile-cache' => (int)$_POST['mobile-cache'],
67
- 'breeze-disable-admin' => (isset($_POST['breeze-admin-cache']) ? '0' : '1'), // 0 is enable, 1 is disable in this case.
68
- 'breeze-display-clean' => '1',
69
- 'breeze-include-inline-js' => (isset($_POST['include-inline-js']) ? '1' : '0'),
70
- 'breeze-include-inline-css' => (isset($_POST['include-inline-css']) ? '1' : '0'),
71
- );
72
-
73
- breeze_update_option( 'basic_settings', $basic, true );
74
-
75
- // Storage infomation to cache pages
76
- Breeze_ConfigCache::factory()->write();
77
- Breeze_ConfigCache::factory()->write_config_cache();
78
-
79
- // Turn on WP_CACHE to support advanced-cache file
80
- if (isset($_POST['cache-system'])) {
81
- Breeze_ConfigCache::factory()->toggle_caching(true);
82
- } else {
83
- Breeze_ConfigCache::factory()->toggle_caching(false);
84
- }
85
-
86
- // Reschedule cron events
87
- if(isset($_POST['cache-system'])){
88
- Breeze_PurgeCacheTime::factory()->unschedule_events();
89
- Breeze_PurgeCacheTime::factory()->schedule_events();
90
- }
91
- // Add expires header
92
- self::update_htaccess();
93
-
94
- //delete cache after settings
95
- do_action('breeze_clear_all_cache');
96
-
97
- }
98
- }
99
- // Advanced options tab
100
- if (isset($_REQUEST['breeze_advanced_action']) && $_REQUEST['breeze_advanced_action'] == 'breeze_advanced_settings') {
101
- if (isset($_POST['breeze_settings_advanced_nonce']) && wp_verify_nonce($_POST['breeze_settings_advanced_nonce'], 'breeze_settings_advanced')) {
102
- $exclude_urls = $this->string_convert_arr(sanitize_textarea_field($_POST['exclude-urls']));
103
- $exclude_css = $this->string_convert_arr(sanitize_textarea_field($_POST['exclude-css']));
104
- $exclude_js = $this->string_convert_arr(sanitize_textarea_field($_POST['exclude-js']));
105
- $move_to_footer_js = $defer_js = array();
106
-
107
- if(!empty($exclude_js)){
108
- $exclude_js = array_unique($exclude_js);
109
- }
110
-
111
- if(!empty($exclude_css)){
112
- $exclude_css = array_unique($exclude_css);
113
- }
114
-
115
- if (!empty($_POST['move-to-footer-js'])) {
116
- foreach ($_POST['move-to-footer-js'] as $url) {
117
- if (trim($url) == '') continue;
118
- $url = current(explode('?', $url, 2));
119
- $move_to_footer_js[sanitize_text_field($url)] = sanitize_text_field($url);
120
- }
121
- }
122
-
123
- if (!empty($_POST['defer-js'])) {
124
- foreach ($_POST['defer-js'] as $url) {
125
- if (trim($url) == '') continue;
126
- $url = current(explode('?', $url, 2));
127
- $defer_js[sanitize_text_field($url)] = sanitize_text_field($url);
128
- }
129
- }
130
-
131
- $advanced = array(
132
- 'breeze-exclude-urls' => $exclude_urls,
133
- 'breeze-group-css' => (isset($_POST['group-css']) ? '1' : '0'),
134
- 'breeze-group-js' => (isset($_POST['group-js']) ? '1' : '0'),
135
- 'breeze-exclude-css' => $exclude_css,
136
- 'breeze-exclude-js' => $exclude_js,
137
- 'breeze-move-to-footer-js' => $move_to_footer_js,
138
- 'breeze-defer-js' => $defer_js
139
- );
140
-
141
- breeze_update_option( 'advanced_settings', $advanced, true );
142
-
143
- WP_Filesystem();
144
- // Storage infomation to cache pages
145
- Breeze_ConfigCache::factory()->write_config_cache();
146
-
147
- //delete cache after settings
148
- do_action('breeze_clear_all_cache');
149
-
150
- }
151
- }
152
-
153
- // Database option tab
154
- if (
155
- isset( $_REQUEST['breeze_database_action'] ) &&
156
- 'breeze_database_settings' === $_REQUEST['breeze_database_action'] &&
157
- isset( $_POST['breeze_settings_database_nonce'] ) &&
158
- wp_verify_nonce( $_POST['breeze_settings_database_nonce'], 'breeze_settings_database' ) &&
159
- ! empty( $_POST['clean'] ) && is_array( $_POST['clean'] )
160
- ) {
161
- self::optimize_database( $_POST['clean'] );
162
-
163
- //return current page
164
- if ( ! empty( $_REQUEST['_wp_http_referer'] ) ) {
165
- $url = remove_query_arg( 'save-settings', $_REQUEST['_wp_http_referer'] );
166
- wp_safe_redirect( add_query_arg( 'database-cleanup', 'success', $url ) );
167
- exit;
168
- }
169
- }
170
-
171
- // Cdn option tab
172
- if (isset($_REQUEST['breeze_cdn_action']) && $_REQUEST['breeze_cdn_action'] == 'breeze_cdn_settings') {
173
- if (isset($_POST['breeze_settings_cdn_nonce']) && wp_verify_nonce($_POST['breeze_settings_cdn_nonce'], 'breeze_settings_cdn')) {
174
- $cdn_content = array();
175
- $exclude_content = array();
176
- if(!empty($_POST['cdn-content'])){
177
- $cdn_content = explode(',',sanitize_text_field($_POST['cdn-content']));
178
- $cdn_content = array_unique($cdn_content);
179
- }
180
- if(!empty($_POST['cdn-exclude-content'])){
181
- $exclude_content = explode(',',sanitize_text_field($_POST['cdn-exclude-content']));
182
- $exclude_content = array_unique($exclude_content);
183
- }
184
-
185
- $cdn_url = ( isset( $_POST['cdn-url'] ) ? sanitize_text_field( $_POST['cdn-url'] ) : '' );
186
- if ( ! empty( $cdn_url ) ) {
187
- $http_schema = parse_url( $cdn_url, PHP_URL_SCHEME );
188
-
189
- $cdn_url = ltrim( $cdn_url, 'https:' );
190
- $cdn_url = '//' . ltrim( $cdn_url, '//' );
191
-
192
- if ( ! empty( $http_schema ) ) {
193
- $cdn_url = $http_schema . ':' . $cdn_url;
194
- }
195
- }
196
-
197
- $cdn = array(
198
- 'cdn-active' => (isset($_POST['activate-cdn']) ? '1' : '0'),
199
- 'cdn-url' => $cdn_url,
200
- 'cdn-content' => $cdn_content,
201
- 'cdn-exclude-content' => $exclude_content,
202
- 'cdn-relative-path' =>(isset($_POST['cdn-relative-path']) ? '1' : '0'),
203
- );
204
-
205
- breeze_update_option( 'cdn_integration', $cdn, true );
206
-
207
- //delete cache after settings
208
- do_action('breeze_clear_all_cache');
209
-
210
- }
211
- }
212
-
213
- // Varnish option tab
214
- if (isset($_REQUEST['breeze_varnish_action']) && $_REQUEST['breeze_varnish_action'] == 'breeze_varnish_settings') {
215
- if (isset($_POST['breeze_settings_varnish_nonce']) && wp_verify_nonce($_POST['breeze_settings_varnish_nonce'], 'breeze_settings_varnish')) {
216
- $varnish = array(
217
- 'auto-purge-varnish' => (isset($_POST['auto-purge-varnish']) ? '1' : '0'),
218
- 'breeze-varnish-server-ip' => preg_replace('/[^a-zA-Z0-9\-\_\.]*/','',$_POST['varnish-server-ip'])
219
- );
220
-
221
- breeze_update_option( 'varnish_cache', $varnish, true );
222
-
223
- // Clear varnish cache after settings
224
- do_action('breeze_clear_varnish');
225
- }
226
- }
227
-
228
-
229
- //return current page
230
- if ( ! empty( $_REQUEST['_wp_http_referer'] ) ) {
231
- $url = remove_query_arg( 'database-cleanup', $_REQUEST['_wp_http_referer'] );
232
- wp_safe_redirect( add_query_arg( 'save-settings', 'success', $url ) );
233
- exit;
234
- }
235
-
236
- return true;
237
- }
238
-
239
- /*
240
- * function add expires header to .htaccess
241
- */
242
- public static function add_expires_header( $clean = false, $conditional_regex = '' ) {
243
- $args = array(
244
- 'before' => '#Expires headers configuration added by BREEZE WP CACHE plugin',
245
- 'after' => '#End of expires headers configuration',
246
- );
247
-
248
- if ( $clean ) {
249
- $args['clean'] = true;
250
- } else {
251
- $args['content'] = 'SetEnv BREEZE_BROWSER_CACHE_ON 1' . PHP_EOL .
252
- '<IfModule mod_expires.c>' . PHP_EOL .
253
- ' ExpiresActive On' . PHP_EOL .
254
- ' ExpiresByType image/gif "access 1 year"' . PHP_EOL .
255
- ' ExpiresByType image/jpg "access 1 year"' . PHP_EOL .
256
- ' ExpiresByType image/jpeg "access 1 year"' . PHP_EOL .
257
- ' ExpiresByType image/png "access 1 year"' . PHP_EOL .
258
- ' ExpiresByType image/x-icon "access 1 year"' . PHP_EOL .
259
- ' ExpiresByType text/html "access plus 0 seconds"' . PHP_EOL .
260
- ' ExpiresByType text/xml "access plus 0 seconds"' . PHP_EOL .
261
- ' ExpiresByType text/css "access 1 month"' . PHP_EOL .
262
- ' ExpiresByType text/javascript "access 1 month"' . PHP_EOL .
263
- ' ExpiresByType application/xml "access plus 0 seconds"' . PHP_EOL .
264
- ' ExpiresByType application/json "access plus 0 seconds"' . PHP_EOL .
265
- ' ExpiresByType application/javascript "access 1 month"' . PHP_EOL .
266
- ' ExpiresByType application/x-javascript "access 1 month"' . PHP_EOL .
267
- ' ExpiresByType application/xhtml-xml "access 1 month"' . PHP_EOL .
268
- ' ExpiresByType application/pdf "access 1 month"' . PHP_EOL .
269
- ' ExpiresByType application/x-shockwave-flash "access 1 month"' . PHP_EOL .
270
- ' ExpiresDefault "access 1 month"' . PHP_EOL .
271
- '</IfModule>' . PHP_EOL;
272
-
273
- $args['conditions'] = array(
274
- 'mod_expires',
275
- 'ExpiresActive',
276
- 'ExpiresDefault',
277
- 'ExpiresByType',
278
- );
279
-
280
- if ( ! empty( $conditional_regex ) ) {
281
- $args['content'] = '<If "' . $conditional_regex . '">' . PHP_EOL . $args['content'] . '</If>' . PHP_EOL;
282
- };
283
- }
284
-
285
- return self::write_htaccess( $args );
286
- }
287
-
288
- /*
289
- * function add gzip header to .htaccess
290
- */
291
- public static function add_gzip_htacess( $clean = false, $conditional_regex = '' ) {
292
- $args = array(
293
- 'before' => '# Begin GzipofBreezeWPCache',
294
- 'after' => '# End GzipofBreezeWPCache',
295
- );
296
-
297
- if ( $clean ) {
298
- $args['clean'] = true;
299
- } else {
300
- $args['content'] = 'SetEnv BREEZE_GZIP_ON 1' . PHP_EOL .
301
- '<IfModule mod_deflate.c>' . PHP_EOL .
302
- ' AddType x-font/woff .woff' . PHP_EOL .
303
- ' AddOutputFilterByType DEFLATE image/svg+xml' . PHP_EOL .
304
- ' AddOutputFilterByType DEFLATE text/plain' . PHP_EOL .
305
- ' AddOutputFilterByType DEFLATE text/html' . PHP_EOL .
306
- ' AddOutputFilterByType DEFLATE text/xml' . PHP_EOL .
307
- ' AddOutputFilterByType DEFLATE text/css' . PHP_EOL .
308
- ' AddOutputFilterByType DEFLATE text/javascript' . PHP_EOL .
309
- ' AddOutputFilterByType DEFLATE application/xml' . PHP_EOL .
310
- ' AddOutputFilterByType DEFLATE application/xhtml+xml' . PHP_EOL .
311
- ' AddOutputFilterByType DEFLATE application/rss+xml' . PHP_EOL .
312
- ' AddOutputFilterByType DEFLATE application/javascript' . PHP_EOL .
313
- ' AddOutputFilterByType DEFLATE application/x-javascript' . PHP_EOL .
314
- ' AddOutputFilterByType DEFLATE application/x-font-ttf' . PHP_EOL .
315
- ' AddOutputFilterByType DEFLATE application/vnd.ms-fontobject' . PHP_EOL .
316
- ' AddOutputFilterByType DEFLATE font/opentype font/ttf font/eot font/otf' . PHP_EOL .
317
- '</IfModule>' . PHP_EOL;
318
-
319
- $args['conditions'] = array(
320
- 'mod_deflate',
321
- 'AddOutputFilterByType',
322
- 'AddType',
323
- 'GzipofBreezeWPCache',
324
- );
325
-
326
- if ( ! empty( $conditional_regex ) ) {
327
- $args['content'] = '<If "' . $conditional_regex . '">' . PHP_EOL . $args['content'] . '</If>' . PHP_EOL;
328
- };
329
- }
330
-
331
- return self::write_htaccess( $args );
332
- }
333
-
334
- /**
335
- * Trigger update to htaccess file.
336
- *
337
- * @param bool $clean If true, will clear custom .htaccess rules.
338
- * @return bool
339
- */
340
- public static function update_htaccess( $clean = false ) {
341
- if ( $clean ) {
342
- self::add_expires_header( $clean );
343
- self::add_gzip_htacess( $clean );
344
- return true;
345
- }
346
-
347
- if ( is_multisite() ) {
348
- // Multisite setup.
349
- $supports_conditionals = breeze_is_supported( 'conditional_htaccess' );
350
-
351
- if ( ! $supports_conditionals ) {
352
- // If Apache htaccess conditional directives not available, inherit network-level settings.
353
- $config = get_site_option( 'breeze_basic_settings', array() );
354
-
355
- if ( isset( $config['breeze-active'] ) && '1' === $config['breeze-active'] ) {
356
- self::add_expires_header( ! isset( $config['breeze-browser-cache'] ) || '1' !== $config['breeze-browser-cache'] );
357
- self::add_gzip_htacess( ! isset( $config['breeze-gzip-compression'] ) || '1' !== $config['breeze-gzip-compression'] );
358
- } else {
359
- self::add_expires_header( true );
360
- self::add_gzip_htacess( true );
361
- }
362
-
363
- return true;
364
- }
365
-
366
- $has_browser_cache = false;
367
- $browser_cache_sites = array();
368
- $no_browser_cache_sites = array();
369
- $browser_cache_regex = '';
370
- $has_gzip_compress = false;
371
- $gzip_compress_sites = array();
372
- $no_gzip_compress_sites = array();
373
- $gzip_compress_regex = '';
374
-
375
- $blogs = get_sites(
376
- array(
377
- 'fields' => 'ids',
378
- )
379
- );
380
-
381
- global $breeze_network_subsite_settings;
382
- $breeze_network_subsite_settings = true;
383
-
384
- foreach ( $blogs as $blog_id ) {
385
- switch_to_blog( $blog_id );
386
- $site_url = preg_quote( preg_replace( '(^https?://)', '', site_url() ) );
387
- $config = breeze_get_option( 'basic_settings' );
388
- if ( '1' === $config['breeze-active'] ) {
389
- if ( '1' === $config['breeze-browser-cache'] ) {
390
- $has_browser_cache = true;
391
- $browser_cache_sites[] = $site_url;
392
- } else {
393
- $no_browser_cache_sites[] = $site_url;
394
- }
395
- if ( '1' === $config['breeze-gzip-compression'] ) {
396
- $has_gzip_compress = true;
397
- $gzip_compress_sites[] = $site_url;
398
- } else {
399
- $no_gzip_compress_sites[] = $site_url;
400
- }
401
- } else {
402
- $no_browser_cache_sites[] = $site_url;
403
- $no_gzip_compress_sites[] = $site_url;
404
- }
405
- restore_current_blog();
406
- }
407
-
408
- $breeze_network_subsite_settings = false;
409
-
410
- $rules = array(
411
- 'browser_cache' => 'add_expires_header',
412
- 'gzip_compress' => 'add_gzip_htacess',
413
- );
414
- // Loop through caching type rules.
415
- foreach ( $rules as $var_name => $method_name ) {
416
- $has_cache_var = 'has_' . $var_name;
417
- if ( ! ${$has_cache_var} ) {
418
- // No sites using rules, clean up.
419
- self::$method_name( true );
420
- } else {
421
- $enabled_sites = $var_name . '_sites';
422
- $disabled_sites = 'no_' . $var_name . '_sites';
423
- $regex_string = '';
424
-
425
- if ( empty( ${$disabled_sites} ) ) {
426
- // Rule is active across sites, do not include conditional directives.
427
- self::$method_name( $clean );
428
- continue;
429
- }
430
-
431
- if ( defined( 'SUBDOMAIN_INSTALL' ) && SUBDOMAIN_INSTALL ) {
432
- // Subdomain sites are matched using host alone.
433
- $regex_string = '%{HTTP_HOST} =~ m#^(' . implode( '|', ${$enabled_sites} ) . ')#';
434
- } else {
435
- // Subdirectory sites are matched using "THE_REQUEST".
436
- $network_site_url = preg_quote( preg_replace( '(^https?://)', '', untrailingslashit( network_site_url() ) ) );
437
-
438
- // Remove host part from URLs.
439
- ${$enabled_sites} = array_filter(
440
- array_map(
441
- function( $url ) use ( $network_site_url ) {
442
- $modified = str_replace( $network_site_url, '', $url );
443
- return empty( $modified ) ? '/' : $modified;
444
- },
445
- ${$enabled_sites}
446
- )
447
- );
448
-
449
- if ( ! empty( ${$enabled_sites} ) ) {
450
- $regex_string = '%{THE_REQUEST} =~ m#^GET (' . implode( '|', ${$enabled_sites} ) . ')#';
451
- }
452
-
453
- // Remove main site URL from disabled sites array.
454
- $network_site_url_index = array_search( $network_site_url, ${$disabled_sites} );
455
- if ( false !== $network_site_url_index ) {
456
- unset( ${$disabled_sites[ $network_site_url_index ]} );
457
- }
458
- // Remove host part from URLs.
459
- ${$disabled_sites} = array_filter(
460
- array_map(
461
- function( $url ) use ( $network_site_url ) {
462
- $modified = str_replace( $network_site_url, '', $url );
463
- return empty( $modified ) ? '/' : $modified;
464
- },
465
- ${$disabled_sites}
466
- )
467
- );
468
- if ( ! empty( ${$disabled_sites} ) ) {
469
- if ( ! empty( ${$enabled_sites} ) ) {
470
- $regex_string .= ' && ';
471
- }
472
- $regex_string .= '%{THE_REQUEST} !~ m#^GET (' . implode( '|', ${$disabled_sites} ) . ')#';
473
- }
474
- }
475
-
476
- // Add conditional rule.
477
- self::$method_name( empty( $regex_string ), $regex_string );
478
- }
479
- }
480
- } else {
481
- // Single-site setup.
482
- $config = breeze_get_option( 'basic_settings' );
483
- if ( '1' === $config['breeze-active'] ) {
484
- self::add_expires_header( '1' !== $config['breeze-browser-cache'] );
485
- self::add_gzip_htacess( '1' !== $config['breeze-gzip-compression'] );
486
- } else {
487
- // Caching not activated, clean up.
488
- self::add_expires_header( true );
489
- self::add_gzip_htacess( true );
490
- return true;
491
- }
492
- }
493
-
494
- return true;
495
- }
496
-
497
- /**
498
- * Add and remove custom blocks from .htaccess.
499
- *
500
- * @param array $args
501
- * @return bool
502
- */
503
- public static function write_htaccess( $args ) {
504
- $htaccess_path = trailingslashit( ABSPATH ) . '.htaccess';
505
-
506
- if ( ! is_super_admin() ) {
507
- return false;
508
- }
509
- // open htaccess file
510
- if ( file_exists( $htaccess_path ) ) {
511
- $htaccess_content = file_get_contents( $htaccess_path );
512
- }
513
- if ( empty( $htaccess_content ) ) {
514
- return false;
515
- }
516
-
517
- // Remove old rules.
518
- $htaccess_content = preg_replace( "/{$args['before']}[\s\S]*{$args['after']}" . PHP_EOL . '/im', '', $htaccess_content );
519
-
520
- if ( ! isset( $args['clean'] ) ) {
521
- if ( isset( $args['conditions'] ) ) {
522
- foreach ( $args['conditions'] as $condition ) {
523
- if ( strpos( $htaccess_content, $condition ) !== false ) {
524
- return false;
525
- }
526
- }
527
- }
528
-
529
- $htaccess_content = $args['before'] . PHP_EOL . $args['content'] . $args['after'] . PHP_EOL . $htaccess_content;
530
- }
531
-
532
- file_put_contents( $htaccess_path, $htaccess_content );
533
- return true;
534
- }
535
-
536
- /*
537
- * Database clean tab
538
- * funtion to clean in database
539
- */
540
- public static function cleanSystem($type){
541
- global $wpdb;
542
- $clean = "";
543
-
544
- switch ($type){
545
- case "revisions":
546
- $clean = "DELETE FROM `$wpdb->posts` WHERE post_type = 'revision';";
547
- $revisions = $wpdb->query( $clean );
548
-
549
- $message = "All post revisions";
550
- break;
551
- case "drafted":
552
- $clean = "DELETE FROM `$wpdb->posts` WHERE post_status = 'auto-draft';";
553
- $autodraft = $wpdb->query( $clean );
554
-
555
- $message = "All auto drafted content";
556
- break;
557
- case "trash":
558
- $clean = "DELETE FROM `$wpdb->posts` WHERE post_status = 'trash';";
559
- $posttrash = $wpdb->query( $clean );
560
-
561
- $message = "All trashed content";
562
- break;
563
- case "comments":
564
- $clean = "DELETE FROM `$wpdb->comments` WHERE comment_approved = 'spam' OR comment_approved = 'trash' ;";
565
- $comments = $wpdb->query( $clean );
566
-
567
- $message = "Comments from trash & spam";
568
- break;
569
- case "trackbacks":
570
- $clean = "DELETE FROM `$wpdb->comments` WHERE comment_type = 'trackback' OR comment_type = 'pingback' ;";
571
- $comments = $wpdb->query( $clean );
572
-
573
- $message = "Trackbacks and pingbacks";
574
- break;
575
- case "transient":
576
- $clean = "DELETE FROM `$wpdb->options` WHERE option_name LIKE '%\_transient\_%' ;";
577
- $comments = $wpdb->query( $clean );
578
-
579
- $message = "Transient options";
580
- break;
581
- }
582
-
583
- return true;
584
- }
585
-
586
- /**
587
- * Database clean tab
588
- * funtion to get number of element to clean in database
589
- *
590
- * @param string $type
591
- */
592
- public static function getElementToClean( $type ) {
593
- global $wpdb;
594
- $return = 0;
595
- switch ($type){
596
- case "revisions":
597
- $element = "SELECT ID FROM `$wpdb->posts` WHERE post_type = 'revision';";
598
- $return = $wpdb->query( $element );
599
- break;
600
- case "drafted":
601
- $element = "SELECT ID FROM `$wpdb->posts` WHERE post_status = 'auto-draft';";
602
- $return = $wpdb->query( $element );
603
- break;
604
- case "trash":
605
- $element = "SELECT ID FROM `$wpdb->posts` WHERE post_status = 'trash';";
606
- $return = $wpdb->query( $element );
607
- break;
608
- case "comments":
609
- $element = "SELECT comment_ID FROM `$wpdb->comments` WHERE comment_approved = 'spam' OR comment_approved = 'trash' ;";
610
- $return = $wpdb->query( $element );
611
- break;
612
- case "trackbacks":
613
- $element = "SELECT comment_ID FROM `$wpdb->comments` WHERE comment_type = 'trackback' OR comment_type = 'pingback' ;";
614
- $return = $wpdb->query( $element );
615
- break;
616
- case "transient":
617
- $element = "SELECT option_id FROM `$wpdb->options` WHERE option_name LIKE '%\_transient\_%' AND option_name != '_transient_doing_cron' ;";
618
- $return = $wpdb->query( $element );
619
- break;
620
- }
621
- return $return;
622
- }
623
-
624
- // Convert string to array
625
- protected function string_convert_arr($input){
626
- $output = array();
627
- if(!empty($input)){
628
- $input = rawurldecode($input);
629
- $input = trim($input);
630
- $input = str_replace(' ', '', $input);
631
- $input = explode("\n",$input);
632
-
633
- foreach ($input as $k => $v){
634
- $output[] = trim($v);
635
- }
636
- }
637
- return $output;
638
- }
639
- //ajax clean cache
640
- public static function breeze_clean_cache() {
641
- // Check whether we're clearing the cache for one subsite on the network.
642
- $is_subsite = is_multisite() && ! is_network_admin();
643
-
644
- // analysis size cache
645
- $cachepath = untrailingslashit( breeze_get_cache_base_path( is_network_admin() ) );
646
-
647
- $size_cache = breeze_get_directory_size( $cachepath );
648
-
649
- // Analyze minification directory sizes.
650
- $files_path = rtrim( WP_CONTENT_DIR, '/' ) . '/cache/breeze-minification';
651
- if ( $is_subsite ) {
652
- $blog_id = get_current_blog_id();
653
- $files_path .= DIRECTORY_SEPARATOR . $blog_id;
654
- }
655
-
656
- $size_cache += breeze_get_directory_size( $files_path, array( 'index.html' ) );
657
-
658
- $result = self::formatBytes( $size_cache );
659
-
660
- //delete minify file
661
- Breeze_MinificationCache::clear_minification();
662
- //delete all cache
663
- Breeze_PurgeCache::breeze_cache_flush();
664
-
665
- return $result;
666
- }
667
-
668
- /*
669
- *Ajax clean cache
670
- *
671
- */
672
- public static function breeze_ajax_clean_cache(){
673
- //check security nonce
674
- check_ajax_referer( '_breeze_purge_cache', 'security' );
675
- $result = self::breeze_clean_cache();
676
-
677
- echo json_encode($result);
678
- exit;
679
- }
680
- /*
681
- * Ajax purge varnish
682
- */
683
- public static function purge_varnish_action(){
684
- //check security
685
- check_ajax_referer( '_breeze_purge_varnish', 'security' );
686
-
687
- do_action('breeze_clear_varnish');
688
-
689
- echo json_encode(array('clear' => true));
690
- exit;
691
- }
692
- /*
693
- * Ajax purge database
694
- */
695
- public static function breeze_ajax_purge_database(){
696
- //check security
697
- check_ajax_referer( '_breeze_purge_database', 'security' );
698
-
699
- $type = array('revisions','drafted','trash','comments','trackbacks','transient');
700
- self::optimize_database( $type );
701
-
702
- echo json_encode(array('clear' => true));
703
- exit;
704
- }
705
- public static function formatBytes($bytes, $precision = 2) {
706
- if ($bytes >= 1073741824) {
707
- $bytes = number_format($bytes / 1073741824, 2);
708
- } elseif ($bytes >= 1048576) {
709
- $bytes = number_format($bytes / 1048576, 2);
710
- } elseif ($bytes >= 1024) {
711
- $bytes = number_format($bytes / 1024, 2);
712
- } elseif ($bytes > 1) {
713
- $bytes = $bytes;
714
- } elseif ($bytes == 1) {
715
- $bytes = $bytes;
716
- } else {
717
- $bytes = '0';
718
- }
719
-
720
- return $bytes;
721
- }
722
-
723
- /**
724
- * Perform database optimization.
725
- *
726
- * @param array $items
727
- */
728
- public static function optimize_database( $items ) {
729
- if ( is_multisite() && is_network_admin() ) {
730
- $sites = get_sites(
731
- array(
732
- 'fields' => 'ids',
733
- )
734
- );
735
-
736
- foreach ( $sites as $blog_id ) {
737
- switch_to_blog( $blog_id );
738
- foreach ( $items as $item ) {
739
- self::cleanSystem( $item );
740
- }
741
- restore_current_blog();
742
- }
743
- } else {
744
- foreach ( $items as $item ) {
745
- self::cleanSystem( $item );
746
- }
747
- }
748
- }
749
-
750
- }
751
-
752
- //init configuration object
753
- new Breeze_Configuration();
 
1
+ <?php
2
+ /**
3
+ * @copyright 2017 Cloudways https://www.cloudways.com
4
+ *
5
+ * This plugin is inspired from WP Speed of Light by JoomUnited.
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_Configuration {
24
+ public function __construct() {
25
+ global $breeze_network_subsite_settings;
26
+ $breeze_network_subsite_settings = false;
27
+ add_action( 'load-settings_page_breeze', array( $this, 'afterLoadConfigPage' ) );
28
+ }
29
+
30
+
31
+ /*
32
+ * function to save settings
33
+ */
34
+ public function afterLoadConfigPage() {
35
+ // Per-site settings (multisite inheriting)
36
+ if (
37
+ is_multisite() &&
38
+ isset( $_REQUEST['inherit-settings'] ) &&
39
+ isset( $_POST['breeze_inherit_settings_nonce'] ) &&
40
+ wp_verify_nonce( $_POST['breeze_inherit_settings_nonce'], 'breeze_inherit_settings' )
41
+ ) {
42
+ $inherit_settings = ( 1 == $_REQUEST['inherit-settings'] ? '1' : '0' );
43
+ update_option( 'breeze_inherit_settings', $inherit_settings );
44
+
45
+ if ( ! isset( $_REQUEST['breeze_basic_action'], $_REQUEST['breeze_advanced_action'] ) ) {
46
+ WP_Filesystem();
47
+ Breeze_ConfigCache::factory()->write_config_cache();
48
+ }
49
+ }
50
+
51
+ // Basic options tab
52
+ if ( isset( $_REQUEST['breeze_basic_action'] ) && $_REQUEST['breeze_basic_action'] == 'breeze_basic_settings' ) {
53
+ if ( isset( $_POST['breeze_settings_basic_nonce'] ) && wp_verify_nonce( $_POST['breeze_settings_basic_nonce'], 'breeze_settings_basic' ) ) {
54
+ WP_Filesystem();
55
+
56
+ $basic = array(
57
+ 'breeze-active' => ( isset( $_POST['cache-system'] ) ? '1' : '0' ),
58
+ 'breeze-ttl' => (int) $_POST['cache-ttl'],
59
+ 'breeze-minify-html' => ( isset( $_POST['minification-html'] ) ? '1' : '0' ),
60
+ 'breeze-minify-css' => ( isset( $_POST['minification-css'] ) ? '1' : '0' ),
61
+ 'breeze-minify-js' => ( isset( $_POST['minification-js'] ) ? '1' : '0' ),
62
+ 'breeze-gzip-compression' => ( isset( $_POST['gzip-compression'] ) ? '1' : '0' ),
63
+ 'breeze-browser-cache' => ( isset( $_POST['browser-cache'] ) ? '1' : '0' ),
64
+ 'breeze-desktop-cache' => (int) $_POST['desktop-cache'],
65
+ 'breeze-mobile-cache' => (int) $_POST['mobile-cache'],
66
+ 'breeze-disable-admin' => ( isset( $_POST['breeze-admin-cache'] ) ? '0' : '1' ), // 0 is enable, 1 is disable in this case.
67
+ 'breeze-display-clean' => '1',
68
+ 'breeze-include-inline-js' => ( isset( $_POST['include-inline-js'] ) ? '1' : '0' ),
69
+ 'breeze-include-inline-css' => ( isset( $_POST['include-inline-css'] ) ? '1' : '0' ),
70
+ );
71
+
72
+ breeze_update_option( 'basic_settings', $basic, true );
73
+
74
+ // Storage infomation to cache pages
75
+ Breeze_ConfigCache::factory()->write();
76
+ Breeze_ConfigCache::factory()->write_config_cache();
77
+
78
+ // Turn on WP_CACHE to support advanced-cache file
79
+ if ( isset( $_POST['cache-system'] ) ) {
80
+ Breeze_ConfigCache::factory()->toggle_caching( true );
81
+ } else {
82
+ Breeze_ConfigCache::factory()->toggle_caching( false );
83
+ }
84
+
85
+ // Reschedule cron events
86
+ if ( isset( $_POST['cache-system'] ) ) {
87
+ Breeze_PurgeCacheTime::factory()->unschedule_events();
88
+ Breeze_PurgeCacheTime::factory()->schedule_events();
89
+ }
90
+ // Add expires header
91
+ self::update_htaccess();
92
+
93
+ //delete cache after settings
94
+ do_action( 'breeze_clear_all_cache' );
95
+
96
+ }
97
+ }
98
+ // Advanced options tab
99
+ if ( isset( $_REQUEST['breeze_advanced_action'] ) && $_REQUEST['breeze_advanced_action'] == 'breeze_advanced_settings' ) {
100
+ if ( isset( $_POST['breeze_settings_advanced_nonce'] ) && wp_verify_nonce( $_POST['breeze_settings_advanced_nonce'], 'breeze_settings_advanced' ) ) {
101
+ $exclude_urls = $this->string_convert_arr( sanitize_textarea_field( $_POST['exclude-urls'] ) );
102
+ $exclude_css = $this->string_convert_arr( sanitize_textarea_field( $_POST['exclude-css'] ) );
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 ) == '' ) {
117
+ continue;
118
+ }
119
+ $url = current( explode( '?', $url, 2 ) );
120
+ $move_to_footer_js[ sanitize_text_field( $url ) ] = sanitize_text_field( $url );
121
+ }
122
+ }
123
+
124
+ if ( ! empty( $_POST['defer-js'] ) ) {
125
+ foreach ( $_POST['defer-js'] as $url ) {
126
+ if ( trim( $url ) == '' ) {
127
+ continue;
128
+ }
129
+ $url = current( explode( '?', $url, 2 ) );
130
+ $defer_js[ sanitize_text_field( $url ) ] = sanitize_text_field( $url );
131
+ }
132
+ }
133
+
134
+ $advanced = array(
135
+ 'breeze-exclude-urls' => $exclude_urls,
136
+ 'breeze-group-css' => ( isset( $_POST['group-css'] ) ? '1' : '0' ),
137
+ 'breeze-group-js' => ( isset( $_POST['group-js'] ) ? '1' : '0' ),
138
+ 'breeze-exclude-css' => $exclude_css,
139
+ 'breeze-exclude-js' => $exclude_js,
140
+ 'breeze-move-to-footer-js' => $move_to_footer_js,
141
+ 'breeze-defer-js' => $defer_js,
142
+ );
143
+
144
+ breeze_update_option( 'advanced_settings', $advanced, true );
145
+
146
+ WP_Filesystem();
147
+ // Storage infomation to cache pages
148
+ Breeze_ConfigCache::factory()->write_config_cache();
149
+
150
+ //delete cache after settings
151
+ do_action( 'breeze_clear_all_cache' );
152
+
153
+ }
154
+ }
155
+
156
+ // Database option tab
157
+ if (
158
+ isset( $_REQUEST['breeze_database_action'] ) &&
159
+ 'breeze_database_settings' === $_REQUEST['breeze_database_action'] &&
160
+ isset( $_POST['breeze_settings_database_nonce'] ) &&
161
+ wp_verify_nonce( $_POST['breeze_settings_database_nonce'], 'breeze_settings_database' ) &&
162
+ ! empty( $_POST['clean'] ) && is_array( $_POST['clean'] )
163
+ ) {
164
+ self::optimize_database( $_POST['clean'] );
165
+
166
+ //return current page
167
+ if ( ! empty( $_REQUEST['_wp_http_referer'] ) ) {
168
+ $url = remove_query_arg( 'save-settings', $_REQUEST['_wp_http_referer'] );
169
+ wp_safe_redirect( add_query_arg( 'database-cleanup', 'success', $url ) );
170
+ exit;
171
+ }
172
+ }
173
+
174
+ // Cdn option tab
175
+ if ( isset( $_REQUEST['breeze_cdn_action'] ) && $_REQUEST['breeze_cdn_action'] == 'breeze_cdn_settings' ) {
176
+ if ( isset( $_POST['breeze_settings_cdn_nonce'] ) && wp_verify_nonce( $_POST['breeze_settings_cdn_nonce'], 'breeze_settings_cdn' ) ) {
177
+ $cdn_content = array();
178
+ $exclude_content = array();
179
+ if ( ! empty( $_POST['cdn-content'] ) ) {
180
+ $cdn_content = explode( ',', sanitize_text_field( $_POST['cdn-content'] ) );
181
+ $cdn_content = array_unique( $cdn_content );
182
+ }
183
+ if ( ! empty( $_POST['cdn-exclude-content'] ) ) {
184
+ $exclude_content = explode( ',', sanitize_text_field( $_POST['cdn-exclude-content'] ) );
185
+ $exclude_content = array_unique( $exclude_content );
186
+ }
187
+
188
+ $cdn_url = ( isset( $_POST['cdn-url'] ) ? sanitize_text_field( $_POST['cdn-url'] ) : '' );
189
+ if ( ! empty( $cdn_url ) ) {
190
+ $http_schema = parse_url( $cdn_url, PHP_URL_SCHEME );
191
+
192
+ $cdn_url = ltrim( $cdn_url, 'https:' );
193
+ $cdn_url = '//' . ltrim( $cdn_url, '//' );
194
+
195
+ if ( ! empty( $http_schema ) ) {
196
+ $cdn_url = $http_schema . ':' . $cdn_url;
197
+ }
198
+ }
199
+
200
+ $cdn = array(
201
+ 'cdn-active' => ( isset( $_POST['activate-cdn'] ) ? '1' : '0' ),
202
+ 'cdn-url' => $cdn_url,
203
+ 'cdn-content' => $cdn_content,
204
+ 'cdn-exclude-content' => $exclude_content,
205
+ 'cdn-relative-path' => ( isset( $_POST['cdn-relative-path'] ) ? '1' : '0' ),
206
+ );
207
+
208
+ breeze_update_option( 'cdn_integration', $cdn, true );
209
+
210
+ //delete cache after settings
211
+ do_action( 'breeze_clear_all_cache' );
212
+
213
+ }
214
+ }
215
+
216
+ // Varnish option tab
217
+ if ( isset( $_REQUEST['breeze_varnish_action'] ) && $_REQUEST['breeze_varnish_action'] == 'breeze_varnish_settings' ) {
218
+ if ( isset( $_POST['breeze_settings_varnish_nonce'] ) && wp_verify_nonce( $_POST['breeze_settings_varnish_nonce'], 'breeze_settings_varnish' ) ) {
219
+ $varnish = array(
220
+ 'auto-purge-varnish' => ( isset( $_POST['auto-purge-varnish'] ) ? '1' : '0' ),
221
+ 'breeze-varnish-server-ip' => preg_replace( '/[^a-zA-Z0-9\-\_\.]*/', '', $_POST['varnish-server-ip'] ),
222
+ );
223
+
224
+ breeze_update_option( 'varnish_cache', $varnish, true );
225
+
226
+ // Clear varnish cache after settings
227
+ do_action( 'breeze_clear_varnish' );
228
+ }
229
+ }
230
+
231
+ //return current page
232
+ if ( ! empty( $_REQUEST['_wp_http_referer'] ) ) {
233
+ $url = remove_query_arg( 'database-cleanup', $_REQUEST['_wp_http_referer'] );
234
+ wp_safe_redirect( add_query_arg( 'save-settings', 'success', $url ) );
235
+ exit;
236
+ }
237
+
238
+ return true;
239
+ }
240
+
241
+ /*
242
+ * function add expires header to .htaccess
243
+ */
244
+ public static function add_expires_header( $clean = false, $conditional_regex = '' ) {
245
+ $args = array(
246
+ 'before' => '#Expires headers configuration added by BREEZE WP CACHE plugin',
247
+ 'after' => '#End of expires headers configuration',
248
+ );
249
+
250
+ if ( $clean ) {
251
+ $args['clean'] = true;
252
+ } else {
253
+ $args['content'] = 'SetEnv BREEZE_BROWSER_CACHE_ON 1' . PHP_EOL .
254
+ '<IfModule mod_expires.c>' . PHP_EOL .
255
+ ' ExpiresActive On' . PHP_EOL .
256
+ ' ExpiresByType image/gif "access 1 year"' . PHP_EOL .
257
+ ' ExpiresByType image/jpg "access 1 year"' . PHP_EOL .
258
+ ' ExpiresByType image/jpeg "access 1 year"' . PHP_EOL .
259
+ ' ExpiresByType image/png "access 1 year"' . PHP_EOL .
260
+ ' ExpiresByType image/x-icon "access 1 year"' . PHP_EOL .
261
+ ' ExpiresByType text/html "access plus 0 seconds"' . PHP_EOL .
262
+ ' ExpiresByType text/xml "access plus 0 seconds"' . PHP_EOL .
263
+ ' ExpiresByType text/css "access 1 month"' . PHP_EOL .
264
+ ' ExpiresByType text/javascript "access 1 month"' . PHP_EOL .
265
+ ' ExpiresByType application/xml "access plus 0 seconds"' . PHP_EOL .
266
+ ' ExpiresByType application/json "access plus 0 seconds"' . PHP_EOL .
267
+ ' ExpiresByType application/javascript "access 1 month"' . PHP_EOL .
268
+ ' ExpiresByType application/x-javascript "access 1 month"' . PHP_EOL .
269
+ ' ExpiresByType application/xhtml-xml "access 1 month"' . PHP_EOL .
270
+ ' ExpiresByType application/pdf "access 1 month"' . PHP_EOL .
271
+ ' ExpiresByType application/x-shockwave-flash "access 1 month"' . PHP_EOL .
272
+ ' ExpiresDefault "access 1 month"' . PHP_EOL .
273
+ '</IfModule>' . PHP_EOL;
274
+
275
+ $args['conditions'] = array(
276
+ 'mod_expires',
277
+ 'ExpiresActive',
278
+ 'ExpiresDefault',
279
+ 'ExpiresByType',
280
+ );
281
+
282
+ if ( ! empty( $conditional_regex ) ) {
283
+ $args['content'] = '<If "' . $conditional_regex . '">' . PHP_EOL . $args['content'] . '</If>' . PHP_EOL;
284
+ };
285
+ }
286
+
287
+ return self::write_htaccess( $args );
288
+ }
289
+
290
+ /*
291
+ * function add gzip header to .htaccess
292
+ */
293
+ public static function add_gzip_htacess( $clean = false, $conditional_regex = '' ) {
294
+ $args = array(
295
+ 'before' => '# Begin GzipofBreezeWPCache',
296
+ 'after' => '# End GzipofBreezeWPCache',
297
+ );
298
+
299
+ if ( $clean ) {
300
+ $args['clean'] = true;
301
+ } else {
302
+ $args['content'] = 'SetEnv BREEZE_GZIP_ON 1' . PHP_EOL .
303
+ '<IfModule mod_deflate.c>' . PHP_EOL .
304
+ ' AddType x-font/woff .woff' . PHP_EOL .
305
+ ' AddOutputFilterByType DEFLATE image/svg+xml' . PHP_EOL .
306
+ ' AddOutputFilterByType DEFLATE text/plain' . PHP_EOL .
307
+ ' AddOutputFilterByType DEFLATE text/html' . PHP_EOL .
308
+ ' AddOutputFilterByType DEFLATE text/xml' . PHP_EOL .
309
+ ' AddOutputFilterByType DEFLATE text/css' . PHP_EOL .
310
+ ' AddOutputFilterByType DEFLATE text/javascript' . PHP_EOL .
311
+ ' AddOutputFilterByType DEFLATE application/xml' . PHP_EOL .
312
+ ' AddOutputFilterByType DEFLATE application/xhtml+xml' . PHP_EOL .
313
+ ' AddOutputFilterByType DEFLATE application/rss+xml' . PHP_EOL .
314
+ ' AddOutputFilterByType DEFLATE application/javascript' . PHP_EOL .
315
+ ' AddOutputFilterByType DEFLATE application/x-javascript' . PHP_EOL .
316
+ ' AddOutputFilterByType DEFLATE application/x-font-ttf' . PHP_EOL .
317
+ ' AddOutputFilterByType DEFLATE application/vnd.ms-fontobject' . PHP_EOL .
318
+ ' AddOutputFilterByType DEFLATE font/opentype font/ttf font/eot font/otf' . PHP_EOL .
319
+ '</IfModule>' . PHP_EOL;
320
+
321
+ $args['conditions'] = array(
322
+ 'mod_deflate',
323
+ 'AddOutputFilterByType',
324
+ 'AddType',
325
+ 'GzipofBreezeWPCache',
326
+ );
327
+
328
+ if ( ! empty( $conditional_regex ) ) {
329
+ $args['content'] = '<If "' . $conditional_regex . '">' . PHP_EOL . $args['content'] . '</If>' . PHP_EOL;
330
+ };
331
+ }
332
+
333
+ return self::write_htaccess( $args );
334
+ }
335
+
336
+ /**
337
+ * Trigger update to htaccess file.
338
+ *
339
+ * @param bool $clean If true, will clear custom .htaccess rules.
340
+ * @return bool
341
+ */
342
+ public static function update_htaccess( $clean = false ) {
343
+ if ( $clean ) {
344
+ self::add_expires_header( $clean );
345
+ self::add_gzip_htacess( $clean );
346
+ return true;
347
+ }
348
+
349
+ if ( is_multisite() ) {
350
+ // Multisite setup.
351
+ $supports_conditionals = breeze_is_supported( 'conditional_htaccess' );
352
+
353
+ if ( ! $supports_conditionals ) {
354
+ // If Apache htaccess conditional directives not available, inherit network-level settings.
355
+ $config = get_site_option( 'breeze_basic_settings', array() );
356
+
357
+ if ( isset( $config['breeze-active'] ) && '1' === $config['breeze-active'] ) {
358
+ self::add_expires_header( ! isset( $config['breeze-browser-cache'] ) || '1' !== $config['breeze-browser-cache'] );
359
+ self::add_gzip_htacess( ! isset( $config['breeze-gzip-compression'] ) || '1' !== $config['breeze-gzip-compression'] );
360
+ } else {
361
+ self::add_expires_header( true );
362
+ self::add_gzip_htacess( true );
363
+ }
364
+
365
+ return true;
366
+ }
367
+
368
+ $has_browser_cache = false;
369
+ $browser_cache_sites = array();
370
+ $no_browser_cache_sites = array();
371
+ $browser_cache_regex = '';
372
+ $has_gzip_compress = false;
373
+ $gzip_compress_sites = array();
374
+ $no_gzip_compress_sites = array();
375
+ $gzip_compress_regex = '';
376
+
377
+ $blogs = get_sites(
378
+ array(
379
+ 'fields' => 'ids',
380
+ )
381
+ );
382
+
383
+ global $breeze_network_subsite_settings;
384
+ $breeze_network_subsite_settings = true;
385
+
386
+ foreach ( $blogs as $blog_id ) {
387
+ switch_to_blog( $blog_id );
388
+ $site_url = preg_quote( preg_replace( '(^https?://)', '', site_url() ) );
389
+ $config = breeze_get_option( 'basic_settings' );
390
+ if ( '1' === $config['breeze-active'] ) {
391
+ if ( '1' === $config['breeze-browser-cache'] ) {
392
+ $has_browser_cache = true;
393
+ $browser_cache_sites[] = $site_url;
394
+ } else {
395
+ $no_browser_cache_sites[] = $site_url;
396
+ }
397
+ if ( '1' === $config['breeze-gzip-compression'] ) {
398
+ $has_gzip_compress = true;
399
+ $gzip_compress_sites[] = $site_url;
400
+ } else {
401
+ $no_gzip_compress_sites[] = $site_url;
402
+ }
403
+ } else {
404
+ $no_browser_cache_sites[] = $site_url;
405
+ $no_gzip_compress_sites[] = $site_url;
406
+ }
407
+ restore_current_blog();
408
+ }
409
+
410
+ $breeze_network_subsite_settings = false;
411
+
412
+ $rules = array(
413
+ 'browser_cache' => 'add_expires_header',
414
+ 'gzip_compress' => 'add_gzip_htacess',
415
+ );
416
+ // Loop through caching type rules.
417
+ foreach ( $rules as $var_name => $method_name ) {
418
+ $has_cache_var = 'has_' . $var_name;
419
+ if ( ! ${$has_cache_var} ) {
420
+ // No sites using rules, clean up.
421
+ self::$method_name( true );
422
+ } else {
423
+ $enabled_sites = $var_name . '_sites';
424
+ $disabled_sites = 'no_' . $var_name . '_sites';
425
+ $regex_string = '';
426
+
427
+ if ( empty( ${$disabled_sites} ) ) {
428
+ // Rule is active across sites, do not include conditional directives.
429
+ self::$method_name( $clean );
430
+ continue;
431
+ }
432
+
433
+ if ( defined( 'SUBDOMAIN_INSTALL' ) && SUBDOMAIN_INSTALL ) {
434
+ // Subdomain sites are matched using host alone.
435
+ $regex_string = '%{HTTP_HOST} =~ m#^(' . implode( '|', ${$enabled_sites} ) . ')#';
436
+ } else {
437
+ // Subdirectory sites are matched using "THE_REQUEST".
438
+ $network_site_url = preg_quote( preg_replace( '(^https?://)', '', untrailingslashit( network_site_url() ) ) );
439
+
440
+ // Remove host part from URLs.
441
+ ${$enabled_sites} = array_filter(
442
+ array_map(
443
+ function( $url ) use ( $network_site_url ) {
444
+ $modified = str_replace( $network_site_url, '', $url );
445
+ return empty( $modified ) ? '/' : $modified;
446
+ },
447
+ ${$enabled_sites}
448
+ )
449
+ );
450
+
451
+ if ( ! empty( ${$enabled_sites} ) ) {
452
+ $regex_string = '%{THE_REQUEST} =~ m#^GET (' . implode( '|', ${$enabled_sites} ) . ')#';
453
+ }
454
+
455
+ // Remove main site URL from disabled sites array.
456
+ $network_site_url_index = array_search( $network_site_url, ${$disabled_sites} );
457
+ if ( false !== $network_site_url_index ) {
458
+ unset( ${$disabled_sites[ $network_site_url_index ]} );
459
+ }
460
+ // Remove host part from URLs.
461
+ ${$disabled_sites} = array_filter(
462
+ array_map(
463
+ function( $url ) use ( $network_site_url ) {
464
+ $modified = str_replace( $network_site_url, '', $url );
465
+ return empty( $modified ) ? '/' : $modified;
466
+ },
467
+ ${$disabled_sites}
468
+ )
469
+ );
470
+ if ( ! empty( ${$disabled_sites} ) ) {
471
+ if ( ! empty( ${$enabled_sites} ) ) {
472
+ $regex_string .= ' && ';
473
+ }
474
+ $regex_string .= '%{THE_REQUEST} !~ m#^GET (' . implode( '|', ${$disabled_sites} ) . ')#';
475
+ }
476
+ }
477
+
478
+ // Add conditional rule.
479
+ self::$method_name( empty( $regex_string ), $regex_string );
480
+ }
481
+ }
482
+ } else {
483
+ // Single-site setup.
484
+ $config = breeze_get_option( 'basic_settings' );
485
+ if ( '1' === $config['breeze-active'] ) {
486
+ self::add_expires_header( '1' !== $config['breeze-browser-cache'] );
487
+ self::add_gzip_htacess( '1' !== $config['breeze-gzip-compression'] );
488
+ } else {
489
+ // Caching not activated, clean up.
490
+ self::add_expires_header( true );
491
+ self::add_gzip_htacess( true );
492
+ return true;
493
+ }
494
+ }
495
+
496
+ return true;
497
+ }
498
+
499
+ /**
500
+ * Add and remove custom blocks from .htaccess.
501
+ *
502
+ * @param array $args
503
+ * @return bool
504
+ */
505
+ public static function write_htaccess( $args ) {
506
+ $htaccess_path = trailingslashit( ABSPATH ) . '.htaccess';
507
+
508
+ if ( ! is_super_admin() ) {
509
+ return false;
510
+ }
511
+ // open htaccess file
512
+ if ( file_exists( $htaccess_path ) ) {
513
+ $htaccess_content = file_get_contents( $htaccess_path );
514
+ }
515
+ if ( empty( $htaccess_content ) ) {
516
+ return false;
517
+ }
518
+
519
+ // Remove old rules.
520
+ $htaccess_content = preg_replace( "/{$args['before']}[\s\S]*{$args['after']}" . PHP_EOL . '/im', '', $htaccess_content );
521
+
522
+ if ( ! isset( $args['clean'] ) ) {
523
+ if ( isset( $args['conditions'] ) ) {
524
+ foreach ( $args['conditions'] as $condition ) {
525
+ if ( strpos( $htaccess_content, $condition ) !== false ) {
526
+ return false;
527
+ }
528
+ }
529
+ }
530
+
531
+ $htaccess_content = $args['before'] . PHP_EOL . $args['content'] . $args['after'] . PHP_EOL . $htaccess_content;
532
+ }
533
+
534
+ file_put_contents( $htaccess_path, $htaccess_content );
535
+ return true;
536
+ }
537
+
538
+ /*
539
+ * Database clean tab
540
+ * funtion to clean in database
541
+ */
542
+ public static function cleanSystem( $type ) {
543
+ global $wpdb;
544
+ $clean = '';
545
+
546
+ switch ( $type ) {
547
+ case 'revisions':
548
+ $clean = "DELETE FROM `$wpdb->posts` WHERE post_type = 'revision';";
549
+ $revisions = $wpdb->query( $clean );
550
+
551
+ $message = 'All post revisions';
552
+ break;
553
+ case 'drafted':
554
+ $clean = "DELETE FROM `$wpdb->posts` WHERE post_status = 'auto-draft';";
555
+ $autodraft = $wpdb->query( $clean );
556
+
557
+ $message = 'All auto drafted content';
558
+ break;
559
+ case 'trash':
560
+ $clean = "DELETE FROM `$wpdb->posts` WHERE post_status = 'trash';";
561
+ $posttrash = $wpdb->query( $clean );
562
+
563
+ $message = 'All trashed content';
564
+ break;
565
+ case 'comments':
566
+ $clean = "DELETE FROM `$wpdb->comments` WHERE comment_approved = 'spam' OR comment_approved = 'trash' ;";
567
+ $comments = $wpdb->query( $clean );
568
+
569
+ $message = 'Comments from trash & spam';
570
+ break;
571
+ case 'trackbacks':
572
+ $clean = "DELETE FROM `$wpdb->comments` WHERE comment_type = 'trackback' OR comment_type = 'pingback' ;";
573
+ $comments = $wpdb->query( $clean );
574
+
575
+ $message = 'Trackbacks and pingbacks';
576
+ break;
577
+ case 'transient':
578
+ $clean = "DELETE FROM `$wpdb->options` WHERE option_name LIKE '%\_transient\_%' ;";
579
+ $comments = $wpdb->query( $clean );
580
+
581
+ $message = 'Transient options';
582
+ break;
583
+ }
584
+
585
+ return true;
586
+ }
587
+
588
+ /**
589
+ * Database clean tab
590
+ * funtion to get number of element to clean in database
591
+ *
592
+ * @param string $type
593
+ */
594
+ public static function getElementToClean( $type ) {
595
+ global $wpdb;
596
+ $return = 0;
597
+ switch ( $type ) {
598
+ case 'revisions':
599
+ $element = "SELECT ID FROM `$wpdb->posts` WHERE post_type = 'revision';";
600
+ $return = $wpdb->query( $element );
601
+ break;
602
+ case 'drafted':
603
+ $element = "SELECT ID FROM `$wpdb->posts` WHERE post_status = 'auto-draft';";
604
+ $return = $wpdb->query( $element );
605
+ break;
606
+ case 'trash':
607
+ $element = "SELECT ID FROM `$wpdb->posts` WHERE post_status = 'trash';";
608
+ $return = $wpdb->query( $element );
609
+ break;
610
+ case 'comments':
611
+ $element = "SELECT comment_ID FROM `$wpdb->comments` WHERE comment_approved = 'spam' OR comment_approved = 'trash' ;";
612
+ $return = $wpdb->query( $element );
613
+ break;
614
+ case 'trackbacks':
615
+ $element = "SELECT comment_ID FROM `$wpdb->comments` WHERE comment_type = 'trackback' OR comment_type = 'pingback' ;";
616
+ $return = $wpdb->query( $element );
617
+ break;
618
+ case 'transient':
619
+ $element = "SELECT option_id FROM `$wpdb->options` WHERE option_name LIKE '%\_transient\_%' AND option_name != '_transient_doing_cron' ;";
620
+ $return = $wpdb->query( $element );
621
+ break;
622
+ }
623
+ return $return;
624
+ }
625
+
626
+ // Convert string to array
627
+ protected function string_convert_arr( $input ) {
628
+ $output = array();
629
+ if ( ! empty( $input ) ) {
630
+ $input = rawurldecode( $input );
631
+ $input = trim( $input );
632
+ $input = str_replace( ' ', '', $input );
633
+ $input = explode( "\n", $input );
634
+
635
+ foreach ( $input as $k => $v ) {
636
+ $output[] = trim( $v );
637
+ }
638
+ }
639
+ return $output;
640
+ }
641
+ //ajax clean cache
642
+ public static function breeze_clean_cache() {
643
+ // Check whether we're clearing the cache for one subsite on the network.
644
+ $is_subsite = is_multisite() && ! is_network_admin();
645
+
646
+ // analysis size cache
647
+ $cachepath = untrailingslashit( breeze_get_cache_base_path( is_network_admin() ) );
648
+
649
+ $size_cache = breeze_get_directory_size( $cachepath );
650
+
651
+ // Analyze minification directory sizes.
652
+ $files_path = rtrim( WP_CONTENT_DIR, '/' ) . '/cache/breeze-minification';
653
+ if ( $is_subsite ) {
654
+ $blog_id = get_current_blog_id();
655
+ $files_path .= DIRECTORY_SEPARATOR . $blog_id;
656
+ }
657
+ $size_cache += breeze_get_directory_size( $files_path, array( 'index.html' ) );
658
+
659
+ $result = self::formatBytes( $size_cache );
660
+
661
+ //delete minify file
662
+ Breeze_MinificationCache::clear_minification();
663
+ //delete all cache
664
+ Breeze_PurgeCache::breeze_cache_flush();
665
+
666
+ return $result;
667
+ }
668
+
669
+ /*
670
+ *Ajax clean cache
671
+ *
672
+ */
673
+ public static function breeze_ajax_clean_cache() {
674
+ //check security nonce
675
+ check_ajax_referer( '_breeze_purge_cache', 'security' );
676
+ $result = self::breeze_clean_cache();
677
+
678
+ echo json_encode( $result );
679
+ exit;
680
+ }
681
+ /*
682
+ * Ajax purge varnish
683
+ */
684
+ public static function purge_varnish_action() {
685
+ //check security
686
+ check_ajax_referer( '_breeze_purge_varnish', 'security' );
687
+
688
+ do_action( 'breeze_clear_varnish' );
689
+
690
+ echo json_encode( array( 'clear' => true ) );
691
+ exit;
692
+ }
693
+ /*
694
+ * Ajax purge database
695
+ */
696
+ public static function breeze_ajax_purge_database() {
697
+ //check security
698
+ check_ajax_referer( '_breeze_purge_database', 'security' );
699
+
700
+ $type = array( 'revisions', 'drafted', 'trash', 'comments', 'trackbacks', 'transient' );
701
+ self::optimize_database( $type );
702
+
703
+ echo json_encode( array( 'clear' => true ) );
704
+ exit;
705
+ }
706
+ public static function formatBytes( $bytes, $precision = 2 ) {
707
+ if ( $bytes >= 1073741824 ) {
708
+ $bytes = number_format( $bytes / 1073741824, 2 );
709
+ } elseif ( $bytes >= 1048576 ) {
710
+ $bytes = number_format( $bytes / 1048576, 2 );
711
+ } elseif ( $bytes >= 1024 ) {
712
+ $bytes = number_format( $bytes / 1024, 2 );
713
+ } elseif ( $bytes > 1 ) {
714
+ $bytes = $bytes;
715
+ } elseif ( $bytes == 1 ) {
716
+ $bytes = $bytes;
717
+ } else {
718
+ $bytes = '0';
719
+ }
720
+
721
+ return $bytes;
722
+ }
723
+
724
+ /**
725
+ * Perform database optimization.
726
+ *
727
+ * @param array $items
728
+ */
729
+ public static function optimize_database( $items ) {
730
+ if ( is_multisite() && is_network_admin() ) {
731
+ $sites = get_sites(
732
+ array(
733
+ 'fields' => 'ids',
734
+ )
735
+ );
736
+
737
+ foreach ( $sites as $blog_id ) {
738
+ switch_to_blog( $blog_id );
739
+ foreach ( $items as $item ) {
740
+ self::cleanSystem( $item );
741
+ }
742
+ restore_current_blog();
743
+ }
744
+ } else {
745
+ foreach ( $items as $item ) {
746
+ self::cleanSystem( $item );
747
+ }
748
+ }
749
+ }
750
+
751
+ }
752
+
753
+ //init configuration object
754
+ new Breeze_Configuration();
inc/cache/Mobile-Detect-2.8.25/Mobile_Detect.php CHANGED
@@ -1,1460 +1,1425 @@
1
- <?php
2
- namespace Cloudways\Breeze\Mobile_Detect;
3
- /**
4
- * Mobile Detect Library
5
- * =====================
6
- *
7
- * Motto: "Every business should have a mobile detection script to detect mobile readers"
8
- *
9
- * Mobile_Detect is a lightweight PHP class for detecting mobile devices (including tablets).
10
- * It uses the User-Agent string combined with specific HTTP headers to detect the mobile environment.
11
- *
12
- * @author Current authors: Serban Ghita <serbanghita@gmail.com>
13
- * Nick Ilyin <nick.ilyin@gmail.com>
14
- *
15
- * Original author: Victor Stanciu <vic.stanciu@gmail.com>
16
- *
17
- * @license Code and contributions have 'MIT License'
18
- * More details: https://github.com/serbanghita/Mobile-Detect/blob/master/LICENSE.txt
19
- *
20
- * @link Homepage: http://mobiledetect.net
21
- * GitHub Repo: https://github.com/serbanghita/Mobile-Detect
22
- * Google Code: http://code.google.com/p/php-mobile-detect/
23
- * README: https://github.com/serbanghita/Mobile-Detect/blob/master/README.md
24
- * HOWTO: https://github.com/serbanghita/Mobile-Detect/wiki/Code-examples
25
- *
26
- * @version 2.8.25
27
- */
28
-
29
- class Mobile_Detect
30
- {
31
- /**
32
- * Mobile detection type.
33
- *
34
- * @deprecated since version 2.6.9
35
- */
36
- const DETECTION_TYPE_MOBILE = 'mobile';
37
-
38
- /**
39
- * Extended detection type.
40
- *
41
- * @deprecated since version 2.6.9
42
- */
43
- const DETECTION_TYPE_EXTENDED = 'extended';
44
-
45
- /**
46
- * A frequently used regular expression to extract version #s.
47
- *
48
- * @deprecated since version 2.6.9
49
- */
50
- const VER = '([\w._\+]+)';
51
-
52
- /**
53
- * Top-level device.
54
- */
55
- const MOBILE_GRADE_A = 'A';
56
-
57
- /**
58
- * Mid-level device.
59
- */
60
- const MOBILE_GRADE_B = 'B';
61
-
62
- /**
63
- * Low-level device.
64
- */
65
- const MOBILE_GRADE_C = 'C';
66
-
67
- /**
68
- * Stores the version number of the current release.
69
- */
70
- const VERSION = '2.8.25';
71
-
72
- /**
73
- * A type for the version() method indicating a string return value.
74
- */
75
- const VERSION_TYPE_STRING = 'text';
76
-
77
- /**
78
- * A type for the version() method indicating a float return value.
79
- */
80
- const VERSION_TYPE_FLOAT = 'float';
81
-
82
- /**
83
- * A cache for resolved matches
84
- * @var array
85
- */
86
- protected $cache = array();
87
-
88
- /**
89
- * The User-Agent HTTP header is stored in here.
90
- * @var string
91
- */
92
- protected $userAgent = null;
93
-
94
- /**
95
- * HTTP headers in the PHP-flavor. So HTTP_USER_AGENT and SERVER_SOFTWARE.
96
- * @var array
97
- */
98
- protected $httpHeaders = array();
99
-
100
- /**
101
- * CloudFront headers. E.g. CloudFront-Is-Desktop-Viewer, CloudFront-Is-Mobile-Viewer & CloudFront-Is-Tablet-Viewer.
102
- * @var array
103
- */
104
- protected $cloudfrontHeaders = array();
105
-
106
- /**
107
- * The matching Regex.
108
- * This is good for debug.
109
- * @var string
110
- */
111
- protected $matchingRegex = null;
112
-
113
- /**
114
- * The matches extracted from the regex expression.
115
- * This is good for debug.
116
- * @var string
117
- */
118
- protected $matchesArray = null;
119
-
120
- /**
121
- * The detection type, using self::DETECTION_TYPE_MOBILE or self::DETECTION_TYPE_EXTENDED.
122
- *
123
- * @deprecated since version 2.6.9
124
- *
125
- * @var string
126
- */
127
- protected $detectionType = self::DETECTION_TYPE_MOBILE;
128
-
129
- /**
130
- * HTTP headers that trigger the 'isMobile' detection
131
- * to be true.
132
- *
133
- * @var array
134
- */
135
- protected static $mobileHeaders = array(
136
-
137
- 'HTTP_ACCEPT' => array('matches' => array(
138
- // Opera Mini; @reference: http://dev.opera.com/articles/view/opera-binary-markup-language/
139
- 'application/x-obml2d',
140
- // BlackBerry devices.
141
- 'application/vnd.rim.html',
142
- 'text/vnd.wap.wml',
143
- 'application/vnd.wap.xhtml+xml'
144
- )),
145
- 'HTTP_X_WAP_PROFILE' => null,
146
- 'HTTP_X_WAP_CLIENTID' => null,
147
- 'HTTP_WAP_CONNECTION' => null,
148
- 'HTTP_PROFILE' => null,
149
- // Reported by Opera on Nokia devices (eg. C3).
150
- 'HTTP_X_OPERAMINI_PHONE_UA' => null,
151
- 'HTTP_X_NOKIA_GATEWAY_ID' => null,
152
- 'HTTP_X_ORANGE_ID' => null,
153
- 'HTTP_X_VODAFONE_3GPDPCONTEXT' => null,
154
- 'HTTP_X_HUAWEI_USERID' => null,
155
- // Reported by Windows Smartphones.
156
- 'HTTP_UA_OS' => null,
157
- // Reported by Verizon, Vodafone proxy system.
158
- 'HTTP_X_MOBILE_GATEWAY' => null,
159
- // Seen this on HTC Sensation. SensationXE_Beats_Z715e.
160
- 'HTTP_X_ATT_DEVICEID' => null,
161
- // Seen this on a HTC.
162
- 'HTTP_UA_CPU' => array('matches' => array('ARM')),
163
- );
164
-
165
- /**
166
- * List of mobile devices (phones).
167
- *
168
- * @var array
169
- */
170
- protected static $phoneDevices = array(
171
- 'iPhone' => '\biPhone\b|\biPod\b', // |\biTunes
172
- 'BlackBerry' => 'BlackBerry|\bBB10\b|rim[0-9]+',
173
- 'HTC' => 'HTC|HTC.*(Sensation|Evo|Vision|Explorer|6800|8100|8900|A7272|S510e|C110e|Legend|Desire|T8282)|APX515CKT|Qtek9090|APA9292KT|HD_mini|Sensation.*Z710e|PG86100|Z715e|Desire.*(A8181|HD)|ADR6200|ADR6400L|ADR6425|001HT|Inspire 4G|Android.*\bEVO\b|T-Mobile G1|Z520m',
174
- 'Nexus' => 'Nexus One|Nexus S|Galaxy.*Nexus|Android.*Nexus.*Mobile|Nexus 4|Nexus 5|Nexus 6',
175
- // @todo: Is 'Dell Streak' a tablet or a phone? ;)
176
- 'Dell' => 'Dell.*Streak|Dell.*Aero|Dell.*Venue|DELL.*Venue Pro|Dell Flash|Dell Smoke|Dell Mini 3iX|XCD28|XCD35|\b001DL\b|\b101DL\b|\bGS01\b',
177
- 'Motorola' => 'Motorola|DROIDX|DROID BIONIC|\bDroid\b.*Build|Android.*Xoom|HRI39|MOT-|A1260|A1680|A555|A853|A855|A953|A955|A956|Motorola.*ELECTRIFY|Motorola.*i1|i867|i940|MB200|MB300|MB501|MB502|MB508|MB511|MB520|MB525|MB526|MB611|MB612|MB632|MB810|MB855|MB860|MB861|MB865|MB870|ME501|ME502|ME511|ME525|ME600|ME632|ME722|ME811|ME860|ME863|ME865|MT620|MT710|MT716|MT720|MT810|MT870|MT917|Motorola.*TITANIUM|WX435|WX445|XT300|XT301|XT311|XT316|XT317|XT319|XT320|XT390|XT502|XT530|XT531|XT532|XT535|XT603|XT610|XT611|XT615|XT681|XT701|XT702|XT711|XT720|XT800|XT806|XT860|XT862|XT875|XT882|XT883|XT894|XT901|XT907|XT909|XT910|XT912|XT928|XT926|XT915|XT919|XT925|XT1021|\bMoto E\b',
178
- 'Samsung' => '\bSamsung\b|SM-G9250|GT-19300|SGH-I337|BGT-S5230|GT-B2100|GT-B2700|GT-B2710|GT-B3210|GT-B3310|GT-B3410|GT-B3730|GT-B3740|GT-B5510|GT-B5512|GT-B5722|GT-B6520|GT-B7300|GT-B7320|GT-B7330|GT-B7350|GT-B7510|GT-B7722|GT-B7800|GT-C3010|GT-C3011|GT-C3060|GT-C3200|GT-C3212|GT-C3212I|GT-C3262|GT-C3222|GT-C3300|GT-C3300K|GT-C3303|GT-C3303K|GT-C3310|GT-C3322|GT-C3330|GT-C3350|GT-C3500|GT-C3510|GT-C3530|GT-C3630|GT-C3780|GT-C5010|GT-C5212|GT-C6620|GT-C6625|GT-C6712|GT-E1050|GT-E1070|GT-E1075|GT-E1080|GT-E1081|GT-E1085|GT-E1087|GT-E1100|GT-E1107|GT-E1110|GT-E1120|GT-E1125|GT-E1130|GT-E1160|GT-E1170|GT-E1175|GT-E1180|GT-E1182|GT-E1200|GT-E1210|GT-E1225|GT-E1230|GT-E1390|GT-E2100|GT-E2120|GT-E2121|GT-E2152|GT-E2220|GT-E2222|GT-E2230|GT-E2232|GT-E2250|GT-E2370|GT-E2550|GT-E2652|GT-E3210|GT-E3213|GT-I5500|GT-I5503|GT-I5700|GT-I5800|GT-I5801|GT-I6410|GT-I6420|GT-I7110|GT-I7410|GT-I7500|GT-I8000|GT-I8150|GT-I8160|GT-I8190|GT-I8320|GT-I8330|GT-I8350|GT-I8530|GT-I8700|GT-I8703|GT-I8910|GT-I9000|GT-I9001|GT-I9003|GT-I9010|GT-I9020|GT-I9023|GT-I9070|GT-I9082|GT-I9100|GT-I9103|GT-I9220|GT-I9250|GT-I9300|GT-I9305|GT-I9500|GT-I9505|GT-M3510|GT-M5650|GT-M7500|GT-M7600|GT-M7603|GT-M8800|GT-M8910|GT-N7000|GT-S3110|GT-S3310|GT-S3350|GT-S3353|GT-S3370|GT-S3650|GT-S3653|GT-S3770|GT-S3850|GT-S5210|GT-S5220|GT-S5229|GT-S5230|GT-S5233|GT-S5250|GT-S5253|GT-S5260|GT-S5263|GT-S5270|GT-S5300|GT-S5330|GT-S5350|GT-S5360|GT-S5363|GT-S5369|GT-S5380|GT-S5380D|GT-S5560|GT-S5570|GT-S5600|GT-S5603|GT-S5610|GT-S5620|GT-S5660|GT-S5670|GT-S5690|GT-S5750|GT-S5780|GT-S5830|GT-S5839|GT-S6102|GT-S6500|GT-S7070|GT-S7200|GT-S7220|GT-S7230|GT-S7233|GT-S7250|GT-S7500|GT-S7530|GT-S7550|GT-S7562|GT-S7710|GT-S8000|GT-S8003|GT-S8500|GT-S8530|GT-S8600|SCH-A310|SCH-A530|SCH-A570|SCH-A610|SCH-A630|SCH-A650|SCH-A790|SCH-A795|SCH-A850|SCH-A870|SCH-A890|SCH-A930|SCH-A950|SCH-A970|SCH-A990|SCH-I100|SCH-I110|SCH-I400|SCH-I405|SCH-I500|SCH-I510|SCH-I515|SCH-I600|SCH-I730|SCH-I760|SCH-I770|SCH-I830|SCH-I910|SCH-I920|SCH-I959|SCH-LC11|SCH-N150|SCH-N300|SCH-R100|SCH-R300|SCH-R351|SCH-R400|SCH-R410|SCH-T300|SCH-U310|SCH-U320|SCH-U350|SCH-U360|SCH-U365|SCH-U370|SCH-U380|SCH-U410|SCH-U430|SCH-U450|SCH-U460|SCH-U470|SCH-U490|SCH-U540|SCH-U550|SCH-U620|SCH-U640|SCH-U650|SCH-U660|SCH-U700|SCH-U740|SCH-U750|SCH-U810|SCH-U820|SCH-U900|SCH-U940|SCH-U960|SCS-26UC|SGH-A107|SGH-A117|SGH-A127|SGH-A137|SGH-A157|SGH-A167|SGH-A177|SGH-A187|SGH-A197|SGH-A227|SGH-A237|SGH-A257|SGH-A437|SGH-A517|SGH-A597|SGH-A637|SGH-A657|SGH-A667|SGH-A687|SGH-A697|SGH-A707|SGH-A717|SGH-A727|SGH-A737|SGH-A747|SGH-A767|SGH-A777|SGH-A797|SGH-A817|SGH-A827|SGH-A837|SGH-A847|SGH-A867|SGH-A877|SGH-A887|SGH-A897|SGH-A927|SGH-B100|SGH-B130|SGH-B200|SGH-B220|SGH-C100|SGH-C110|SGH-C120|SGH-C130|SGH-C140|SGH-C160|SGH-C170|SGH-C180|SGH-C200|SGH-C207|SGH-C210|SGH-C225|SGH-C230|SGH-C417|SGH-C450|SGH-D307|SGH-D347|SGH-D357|SGH-D407|SGH-D415|SGH-D780|SGH-D807|SGH-D980|SGH-E105|SGH-E200|SGH-E315|SGH-E316|SGH-E317|SGH-E335|SGH-E590|SGH-E635|SGH-E715|SGH-E890|SGH-F300|SGH-F480|SGH-I200|SGH-I300|SGH-I320|SGH-I550|SGH-I577|SGH-I600|SGH-I607|SGH-I617|SGH-I627|SGH-I637|SGH-I677|SGH-I700|SGH-I717|SGH-I727|SGH-i747M|SGH-I777|SGH-I780|SGH-I827|SGH-I847|SGH-I857|SGH-I896|SGH-I897|SGH-I900|SGH-I907|SGH-I917|SGH-I927|SGH-I937|SGH-I997|SGH-J150|SGH-J200|SGH-L170|SGH-L700|SGH-M110|SGH-M150|SGH-M200|SGH-N105|SGH-N500|SGH-N600|SGH-N620|SGH-N625|SGH-N700|SGH-N710|SGH-P107|SGH-P207|SGH-P300|SGH-P310|SGH-P520|SGH-P735|SGH-P777|SGH-Q105|SGH-R210|SGH-R220|SGH-R225|SGH-S105|SGH-S307|SGH-T109|SGH-T119|SGH-T139|SGH-T209|SGH-T219|SGH-T229|SGH-T239|SGH-T249|SGH-T259|SGH-T309|SGH-T319|SGH-T329|SGH-T339|SGH-T349|SGH-T359|SGH-T369|SGH-T379|SGH-T409|SGH-T429|SGH-T439|SGH-T459|SGH-T469|SGH-T479|SGH-T499|SGH-T509|SGH-T519|SGH-T539|SGH-T559|SGH-T589|SGH-T609|SGH-T619|SGH-T629|SGH-T639|SGH-T659|SGH-T669|SGH-T679|SGH-T709|SGH-T719|SGH-T729|SGH-T739|SGH-T746|SGH-T749|SGH-T759|SGH-T769|SGH-T809|SGH-T819|SGH-T839|SGH-T919|SGH-T929|SGH-T939|SGH-T959|SGH-T989|SGH-U100|SGH-U200|SGH-U800|SGH-V205|SGH-V206|SGH-X100|SGH-X105|SGH-X120|SGH-X140|SGH-X426|SGH-X427|SGH-X475|SGH-X495|SGH-X497|SGH-X507|SGH-X600|SGH-X610|SGH-X620|SGH-X630|SGH-X700|SGH-X820|SGH-X890|SGH-Z130|SGH-Z150|SGH-Z170|SGH-ZX10|SGH-ZX20|SHW-M110|SPH-A120|SPH-A400|SPH-A420|SPH-A460|SPH-A500|SPH-A560|SPH-A600|SPH-A620|SPH-A660|SPH-A700|SPH-A740|SPH-A760|SPH-A790|SPH-A800|SPH-A820|SPH-A840|SPH-A880|SPH-A900|SPH-A940|SPH-A960|SPH-D600|SPH-D700|SPH-D710|SPH-D720|SPH-I300|SPH-I325|SPH-I330|SPH-I350|SPH-I500|SPH-I600|SPH-I700|SPH-L700|SPH-M100|SPH-M220|SPH-M240|SPH-M300|SPH-M305|SPH-M320|SPH-M330|SPH-M350|SPH-M360|SPH-M370|SPH-M380|SPH-M510|SPH-M540|SPH-M550|SPH-M560|SPH-M570|SPH-M580|SPH-M610|SPH-M620|SPH-M630|SPH-M800|SPH-M810|SPH-M850|SPH-M900|SPH-M910|SPH-M920|SPH-M930|SPH-N100|SPH-N200|SPH-N240|SPH-N300|SPH-N400|SPH-Z400|SWC-E100|SCH-i909|GT-N7100|GT-N7105|SCH-I535|SM-N900A|SGH-I317|SGH-T999L|GT-S5360B|GT-I8262|GT-S6802|GT-S6312|GT-S6310|GT-S5312|GT-S5310|GT-I9105|GT-I8510|GT-S6790N|SM-G7105|SM-N9005|GT-S5301|GT-I9295|GT-I9195|SM-C101|GT-S7392|GT-S7560|GT-B7610|GT-I5510|GT-S7582|GT-S7530E|GT-I8750|SM-G9006V|SM-G9008V|SM-G9009D|SM-G900A|SM-G900D|SM-G900F|SM-G900H|SM-G900I|SM-G900J|SM-G900K|SM-G900L|SM-G900M|SM-G900P|SM-G900R4|SM-G900S|SM-G900T|SM-G900V|SM-G900W8|SHV-E160K|SCH-P709|SCH-P729|SM-T2558|GT-I9205|SM-G9350|SM-J120F|SM-G920F|SM-G920V|SM-G930F|SM-N910C',
179
- 'LG' => '\bLG\b;|LG[- ]?(C800|C900|E400|E610|E900|E-900|F160|F180K|F180L|F180S|730|855|L160|LS740|LS840|LS970|LU6200|MS690|MS695|MS770|MS840|MS870|MS910|P500|P700|P705|VM696|AS680|AS695|AX840|C729|E970|GS505|272|C395|E739BK|E960|L55C|L75C|LS696|LS860|P769BK|P350|P500|P509|P870|UN272|US730|VS840|VS950|LN272|LN510|LS670|LS855|LW690|MN270|MN510|P509|P769|P930|UN200|UN270|UN510|UN610|US670|US740|US760|UX265|UX840|VN271|VN530|VS660|VS700|VS740|VS750|VS910|VS920|VS930|VX9200|VX11000|AX840A|LW770|P506|P925|P999|E612|D955|D802|MS323)',
180
- 'Sony' => 'SonyST|SonyLT|SonyEricsson|SonyEricssonLT15iv|LT18i|E10i|LT28h|LT26w|SonyEricssonMT27i|C5303|C6902|C6903|C6906|C6943|D2533',
181
- 'Asus' => 'Asus.*Galaxy|PadFone.*Mobile',
182
- 'NokiaLumia' => 'Lumia [0-9]{3,4}',
183
- // http://www.micromaxinfo.com/mobiles/smartphones
184
- // Added because the codes might conflict with Acer Tablets.
185
- 'Micromax' => 'Micromax.*\b(A210|A92|A88|A72|A111|A110Q|A115|A116|A110|A90S|A26|A51|A35|A54|A25|A27|A89|A68|A65|A57|A90)\b',
186
- // @todo Complete the regex.
187
- 'Palm' => 'PalmSource|Palm', // avantgo|blazer|elaine|hiptop|plucker|xiino ;
188
- 'Vertu' => 'Vertu|Vertu.*Ltd|Vertu.*Ascent|Vertu.*Ayxta|Vertu.*Constellation(F|Quest)?|Vertu.*Monika|Vertu.*Signature', // Just for fun ;)
189
- // http://www.pantech.co.kr/en/prod/prodList.do?gbrand=VEGA (PANTECH)
190
- // Most of the VEGA devices are legacy. PANTECH seem to be newer devices based on Android.
191
- 'Pantech' => 'PANTECH|IM-A850S|IM-A840S|IM-A830L|IM-A830K|IM-A830S|IM-A820L|IM-A810K|IM-A810S|IM-A800S|IM-T100K|IM-A725L|IM-A780L|IM-A775C|IM-A770K|IM-A760S|IM-A750K|IM-A740S|IM-A730S|IM-A720L|IM-A710K|IM-A690L|IM-A690S|IM-A650S|IM-A630K|IM-A600S|VEGA PTL21|PT003|P8010|ADR910L|P6030|P6020|P9070|P4100|P9060|P5000|CDM8992|TXT8045|ADR8995|IS11PT|P2030|P6010|P8000|PT002|IS06|CDM8999|P9050|PT001|TXT8040|P2020|P9020|P2000|P7040|P7000|C790',
192
- // http://www.fly-phone.com/devices/smartphones/ ; Included only smartphones.
193
- 'Fly' => 'IQ230|IQ444|IQ450|IQ440|IQ442|IQ441|IQ245|IQ256|IQ236|IQ255|IQ235|IQ245|IQ275|IQ240|IQ285|IQ280|IQ270|IQ260|IQ250',
194
- // http://fr.wikomobile.com
195
- 'Wiko' => 'KITE 4G|HIGHWAY|GETAWAY|STAIRWAY|DARKSIDE|DARKFULL|DARKNIGHT|DARKMOON|SLIDE|WAX 4G|RAINBOW|BLOOM|SUNSET|GOA(?!nna)|LENNY|BARRY|IGGY|OZZY|CINK FIVE|CINK PEAX|CINK PEAX 2|CINK SLIM|CINK SLIM 2|CINK +|CINK KING|CINK PEAX|CINK SLIM|SUBLIM',
196
- 'iMobile' => 'i-mobile (IQ|i-STYLE|idea|ZAA|Hitz)',
197
- // Added simvalley mobile just for fun. They have some interesting devices.
198
- // http://www.simvalley.fr/telephonie---gps-_22_telephonie-mobile_telephones_.html
199
- 'SimValley' => '\b(SP-80|XT-930|SX-340|XT-930|SX-310|SP-360|SP60|SPT-800|SP-120|SPT-800|SP-140|SPX-5|SPX-8|SP-100|SPX-8|SPX-12)\b',
200
- // Wolfgang - a brand that is sold by Aldi supermarkets.
201
- // http://www.wolfgangmobile.com/
202
- 'Wolfgang' => 'AT-B24D|AT-AS50HD|AT-AS40W|AT-AS55HD|AT-AS45q2|AT-B26D|AT-AS50Q',
203
- 'Alcatel' => 'Alcatel',
204
- 'Nintendo' => 'Nintendo 3DS',
205
- // http://en.wikipedia.org/wiki/Amoi
206
- 'Amoi' => 'Amoi',
207
- // http://en.wikipedia.org/wiki/INQ
208
- 'INQ' => 'INQ',
209
- // @Tapatalk is a mobile app; http://support.tapatalk.com/threads/smf-2-0-2-os-and-browser-detection-plugin-and-tapatalk.15565/#post-79039
210
- 'GenericPhone' => 'Tapatalk|PDA;|SAGEM|\bmmp\b|pocket|\bpsp\b|symbian|Smartphone|smartfon|treo|up.browser|up.link|vodafone|\bwap\b|nokia|Series40|Series60|S60|SonyEricsson|N900|MAUI.*WAP.*Browser',
211
- );
212
-
213
- /**
214
- * List of tablet devices.
215
- *
216
- * @var array
217
- */
218
- protected static $tabletDevices = array(
219
- // @todo: check for mobile friendly emails topic.
220
- 'iPad' => 'iPad|iPad.*Mobile',
221
- // Removed |^.*Android.*Nexus(?!(?:Mobile).)*$
222
- // @see #442
223
- 'NexusTablet' => 'Android.*Nexus[\s]+(7|9|10)',
224
- 'SamsungTablet' => 'SAMSUNG.*Tablet|Galaxy.*Tab|SC-01C|GT-P1000|GT-P1003|GT-P1010|GT-P3105|GT-P6210|GT-P6800|GT-P6810|GT-P7100|GT-P7300|GT-P7310|GT-P7500|GT-P7510|SCH-I800|SCH-I815|SCH-I905|SGH-I957|SGH-I987|SGH-T849|SGH-T859|SGH-T869|SPH-P100|GT-P3100|GT-P3108|GT-P3110|GT-P5100|GT-P5110|GT-P6200|GT-P7320|GT-P7511|GT-N8000|GT-P8510|SGH-I497|SPH-P500|SGH-T779|SCH-I705|SCH-I915|GT-N8013|GT-P3113|GT-P5113|GT-P8110|GT-N8010|GT-N8005|GT-N8020|GT-P1013|GT-P6201|GT-P7501|GT-N5100|GT-N5105|GT-N5110|SHV-E140K|SHV-E140L|SHV-E140S|SHV-E150S|SHV-E230K|SHV-E230L|SHV-E230S|SHW-M180K|SHW-M180L|SHW-M180S|SHW-M180W|SHW-M300W|SHW-M305W|SHW-M380K|SHW-M380S|SHW-M380W|SHW-M430W|SHW-M480K|SHW-M480S|SHW-M480W|SHW-M485W|SHW-M486W|SHW-M500W|GT-I9228|SCH-P739|SCH-I925|GT-I9200|GT-P5200|GT-P5210|GT-P5210X|SM-T311|SM-T310|SM-T310X|SM-T210|SM-T210R|SM-T211|SM-P600|SM-P601|SM-P605|SM-P900|SM-P901|SM-T217|SM-T217A|SM-T217S|SM-P6000|SM-T3100|SGH-I467|XE500|SM-T110|GT-P5220|GT-I9200X|GT-N5110X|GT-N5120|SM-P905|SM-T111|SM-T2105|SM-T315|SM-T320|SM-T320X|SM-T321|SM-T520|SM-T525|SM-T530NU|SM-T230NU|SM-T330NU|SM-T900|XE500T1C|SM-P605V|SM-P905V|SM-T337V|SM-T537V|SM-T707V|SM-T807V|SM-P600X|SM-P900X|SM-T210X|SM-T230|SM-T230X|SM-T325|GT-P7503|SM-T531|SM-T330|SM-T530|SM-T705|SM-T705C|SM-T535|SM-T331|SM-T800|SM-T700|SM-T537|SM-T807|SM-P907A|SM-T337A|SM-T537A|SM-T707A|SM-T807A|SM-T237|SM-T807P|SM-P607T|SM-T217T|SM-T337T|SM-T807T|SM-T116NQ|SM-P550|SM-T350|SM-T550|SM-T9000|SM-P9000|SM-T705Y|SM-T805|GT-P3113|SM-T710|SM-T810|SM-T815|SM-T360|SM-T533|SM-T113|SM-T335|SM-T715|SM-T560|SM-T670|SM-T677|SM-T377|SM-T567|SM-T357T|SM-T555|SM-T561|SM-T713|SM-T719|SM-T813|SM-T819|SM-T580|SM-T355Y|SM-T280|SM-T817A|SM-T820|SM-W700|SM-P580|SM-T587', // SCH-P709|SCH-P729|SM-T2558|GT-I9205 - Samsung Mega - treat them like a regular phone.
225
- // http://docs.aws.amazon.com/silk/latest/developerguide/user-agent.html
226
- 'Kindle' => 'Kindle|Silk.*Accelerated|Android.*\b(KFOT|KFTT|KFJWI|KFJWA|KFOTE|KFSOWI|KFTHWI|KFTHWA|KFAPWI|KFAPWA|WFJWAE|KFSAWA|KFSAWI|KFASWI|KFARWI|KFFOWI|KFGIWI|KFMEWI)\b|Android.*Silk/[0-9.]+ like Chrome/[0-9.]+ (?!Mobile)',
227
- // Only the Surface tablets with Windows RT are considered mobile.
228
- // http://msdn.microsoft.com/en-us/library/ie/hh920767(v=vs.85).aspx
229
- 'SurfaceTablet' => 'Windows NT [0-9.]+; ARM;.*(Tablet|ARMBJS)',
230
- // http://shopping1.hp.com/is-bin/INTERSHOP.enfinity/WFS/WW-USSMBPublicStore-Site/en_US/-/USD/ViewStandardCatalog-Browse?CatalogCategoryID=JfIQ7EN5lqMAAAEyDcJUDwMT
231
- 'HPTablet' => 'HP Slate (7|8|10)|HP ElitePad 900|hp-tablet|EliteBook.*Touch|HP 8|Slate 21|HP SlateBook 10',
232
- // Watch out for PadFone, see #132.
233
- // http://www.asus.com/de/Tablets_Mobile/Memo_Pad_Products/
234
- 'AsusTablet' => '^.*PadFone((?!Mobile).)*$|Transformer|TF101|TF101G|TF300T|TF300TG|TF300TL|TF700T|TF700KL|TF701T|TF810C|ME171|ME301T|ME302C|ME371MG|ME370T|ME372MG|ME172V|ME173X|ME400C|Slider SL101|\bK00F\b|\bK00C\b|\bK00E\b|\bK00L\b|TX201LA|ME176C|ME102A|\bM80TA\b|ME372CL|ME560CG|ME372CG|ME302KL| K010 | K011 | K017 | K01E |ME572C|ME103K|ME170C|ME171C|\bME70C\b|ME581C|ME581CL|ME8510C|ME181C|P01Y|PO1MA|P01Z',
235
- 'BlackBerryTablet' => 'PlayBook|RIM Tablet',
236
- 'HTCtablet' => 'HTC_Flyer_P512|HTC Flyer|HTC Jetstream|HTC-P715a|HTC EVO View 4G|PG41200|PG09410',
237
- 'MotorolaTablet' => 'xoom|sholest|MZ615|MZ605|MZ505|MZ601|MZ602|MZ603|MZ604|MZ606|MZ607|MZ608|MZ609|MZ615|MZ616|MZ617',
238
- 'NookTablet' => 'Android.*Nook|NookColor|nook browser|BNRV200|BNRV200A|BNTV250|BNTV250A|BNTV400|BNTV600|LogicPD Zoom2',
239
- // http://www.acer.ro/ac/ro/RO/content/drivers
240
- // http://www.packardbell.co.uk/pb/en/GB/content/download (Packard Bell is part of Acer)
241
- // http://us.acer.com/ac/en/US/content/group/tablets
242
- // http://www.acer.de/ac/de/DE/content/models/tablets/
243
- // Can conflict with Micromax and Motorola phones codes.
244
- 'AcerTablet' => 'Android.*; \b(A100|A101|A110|A200|A210|A211|A500|A501|A510|A511|A700|A701|W500|W500P|W501|W501P|W510|W511|W700|G100|G100W|B1-A71|B1-710|B1-711|A1-810|A1-811|A1-830)\b|W3-810|\bA3-A10\b|\bA3-A11\b|\bA3-A20\b|\bA3-A30',
245
- // http://eu.computers.toshiba-europe.com/innovation/family/Tablets/1098744/banner_id/tablet_footerlink/
246
- // http://us.toshiba.com/tablets/tablet-finder
247
- // http://www.toshiba.co.jp/regza/tablet/
248
- 'ToshibaTablet' => 'Android.*(AT100|AT105|AT200|AT205|AT270|AT275|AT300|AT305|AT1S5|AT500|AT570|AT700|AT830)|TOSHIBA.*FOLIO',
249
- // http://www.nttdocomo.co.jp/english/service/developer/smart_phone/technical_info/spec/index.html
250
- // http://www.lg.com/us/tablets
251
- 'LGTablet' => '\bL-06C|LG-V909|LG-V900|LG-V700|LG-V510|LG-V500|LG-V410|LG-V400|LG-VK810\b',
252
- 'FujitsuTablet' => 'Android.*\b(F-01D|F-02F|F-05E|F-10D|M532|Q572)\b',
253
- // Prestigio Tablets http://www.prestigio.com/support
254
- 'PrestigioTablet' => 'PMP3170B|PMP3270B|PMP3470B|PMP7170B|PMP3370B|PMP3570C|PMP5870C|PMP3670B|PMP5570C|PMP5770D|PMP3970B|PMP3870C|PMP5580C|PMP5880D|PMP5780D|PMP5588C|PMP7280C|PMP7280C3G|PMP7280|PMP7880D|PMP5597D|PMP5597|PMP7100D|PER3464|PER3274|PER3574|PER3884|PER5274|PER5474|PMP5097CPRO|PMP5097|PMP7380D|PMP5297C|PMP5297C_QUAD|PMP812E|PMP812E3G|PMP812F|PMP810E|PMP880TD|PMT3017|PMT3037|PMT3047|PMT3057|PMT7008|PMT5887|PMT5001|PMT5002',
255
- // http://support.lenovo.com/en_GB/downloads/default.page?#
256
- 'LenovoTablet' => 'Lenovo TAB|Idea(Tab|Pad)( A1|A10| K1|)|ThinkPad([ ]+)?Tablet|YT3-X90L|YT3-X90F|YT3-X90X|Lenovo.*(S2109|S2110|S5000|S6000|K3011|A3000|A3500|A1000|A2107|A2109|A1107|A5500|A7600|B6000|B8000|B8080)(-|)(FL|F|HV|H|)',
257
- // http://www.dell.com/support/home/us/en/04/Products/tab_mob/tablets
258
- 'DellTablet' => 'Venue 11|Venue 8|Venue 7|Dell Streak 10|Dell Streak 7',
259
- // http://www.yarvik.com/en/matrix/tablets/
260
- 'YarvikTablet' => 'Android.*\b(TAB210|TAB211|TAB224|TAB250|TAB260|TAB264|TAB310|TAB360|TAB364|TAB410|TAB411|TAB420|TAB424|TAB450|TAB460|TAB461|TAB464|TAB465|TAB467|TAB468|TAB07-100|TAB07-101|TAB07-150|TAB07-151|TAB07-152|TAB07-200|TAB07-201-3G|TAB07-210|TAB07-211|TAB07-212|TAB07-214|TAB07-220|TAB07-400|TAB07-485|TAB08-150|TAB08-200|TAB08-201-3G|TAB08-201-30|TAB09-100|TAB09-211|TAB09-410|TAB10-150|TAB10-201|TAB10-211|TAB10-400|TAB10-410|TAB13-201|TAB274EUK|TAB275EUK|TAB374EUK|TAB462EUK|TAB474EUK|TAB9-200)\b',
261
- 'MedionTablet' => 'Android.*\bOYO\b|LIFE.*(P9212|P9514|P9516|S9512)|LIFETAB',
262
- 'ArnovaTablet' => '97G4|AN10G2|AN7bG3|AN7fG3|AN8G3|AN8cG3|AN7G3|AN9G3|AN7dG3|AN7dG3ST|AN7dG3ChildPad|AN10bG3|AN10bG3DT|AN9G2',
263
- // http://www.intenso.de/kategorie_en.php?kategorie=33
264
- // @todo: http://www.nbhkdz.com/read/b8e64202f92a2df129126bff.html - investigate
265
- 'IntensoTablet' => 'INM8002KP|INM1010FP|INM805ND|Intenso Tab|TAB1004',
266
- // IRU.ru Tablets http://www.iru.ru/catalog/soho/planetable/
267
- 'IRUTablet' => 'M702pro',
268
- 'MegafonTablet' => 'MegaFon V9|\bZTE V9\b|Android.*\bMT7A\b',
269
- // http://www.e-boda.ro/tablete-pc.html
270
- 'EbodaTablet' => 'E-Boda (Supreme|Impresspeed|Izzycomm|Essential)',
271
- // http://www.allview.ro/produse/droseries/lista-tablete-pc/
272
- 'AllViewTablet' => 'Allview.*(Viva|Alldro|City|Speed|All TV|Frenzy|Quasar|Shine|TX1|AX1|AX2)',
273
- // http://wiki.archosfans.com/index.php?title=Main_Page
274
- // @note Rewrite the regex format after we add more UAs.
275
- 'ArchosTablet' => '\b(101G9|80G9|A101IT)\b|Qilive 97R|Archos5|\bARCHOS (70|79|80|90|97|101|FAMILYPAD|)(b|c|)(G10| Cobalt| TITANIUM(HD|)| Xenon| Neon|XSK| 2| XS 2| PLATINUM| CARBON|GAMEPAD)\b',
276
- // http://www.ainol.com/plugin.php?identifier=ainol&module=product
277
- 'AinolTablet' => 'NOVO7|NOVO8|NOVO10|Novo7Aurora|Novo7Basic|NOVO7PALADIN|novo9-Spark',
278
- 'NokiaLumiaTablet' => 'Lumia 2520',
279
- // @todo: inspect http://esupport.sony.com/US/p/select-system.pl?DIRECTOR=DRIVER
280
- // Readers http://www.atsuhiro-me.net/ebook/sony-reader/sony-reader-web-browser
281
- // http://www.sony.jp/support/tablet/
282
- 'SonyTablet' => 'Sony.*Tablet|Xperia Tablet|Sony Tablet S|SO-03E|SGPT12|SGPT13|SGPT114|SGPT121|SGPT122|SGPT123|SGPT111|SGPT112|SGPT113|SGPT131|SGPT132|SGPT133|SGPT211|SGPT212|SGPT213|SGP311|SGP312|SGP321|EBRD1101|EBRD1102|EBRD1201|SGP351|SGP341|SGP511|SGP512|SGP521|SGP541|SGP551|SGP621|SGP612|SOT31',
283
- // http://www.support.philips.com/support/catalog/worldproducts.jsp?userLanguage=en&userCountry=cn&categoryid=3G_LTE_TABLET_SU_CN_CARE&title=3G%20tablets%20/%20LTE%20range&_dyncharset=UTF-8
284
- 'PhilipsTablet' => '\b(PI2010|PI3000|PI3100|PI3105|PI3110|PI3205|PI3210|PI3900|PI4010|PI7000|PI7100)\b',
285
- // db + http://www.cube-tablet.com/buy-products.html
286
- 'CubeTablet' => 'Android.*(K8GT|U9GT|U10GT|U16GT|U17GT|U18GT|U19GT|U20GT|U23GT|U30GT)|CUBE U8GT',
287
- // http://www.cobyusa.com/?p=pcat&pcat_id=3001
288
- 'CobyTablet' => 'MID1042|MID1045|MID1125|MID1126|MID7012|MID7014|MID7015|MID7034|MID7035|MID7036|MID7042|MID7048|MID7127|MID8042|MID8048|MID8127|MID9042|MID9740|MID9742|MID7022|MID7010',
289
- // http://www.match.net.cn/products.asp
290
- 'MIDTablet' => 'M9701|M9000|M9100|M806|M1052|M806|T703|MID701|MID713|MID710|MID727|MID760|MID830|MID728|MID933|MID125|MID810|MID732|MID120|MID930|MID800|MID731|MID900|MID100|MID820|MID735|MID980|MID130|MID833|MID737|MID960|MID135|MID860|MID736|MID140|MID930|MID835|MID733|MID4X10',
291
- // http://www.msi.com/support
292
- // @todo Research the Windows Tablets.
293
- 'MSITablet' => 'MSI \b(Primo 73K|Primo 73L|Primo 81L|Primo 77|Primo 93|Primo 75|Primo 76|Primo 73|Primo 81|Primo 91|Primo 90|Enjoy 71|Enjoy 7|Enjoy 10)\b',
294
- // @todo http://www.kyoceramobile.com/support/drivers/
295
- // 'KyoceraTablet' => null,
296
- // @todo http://intexuae.com/index.php/category/mobile-devices/tablets-products/
297
- // 'IntextTablet' => null,
298
- // http://pdadb.net/index.php?m=pdalist&list=SMiT (NoName Chinese Tablets)
299
- // http://www.imp3.net/14/show.php?itemid=20454
300
- 'SMiTTablet' => 'Android.*(\bMID\b|MID-560|MTV-T1200|MTV-PND531|MTV-P1101|MTV-PND530)',
301
- // http://www.rock-chips.com/index.php?do=prod&pid=2
302
- 'RockChipTablet' => 'Android.*(RK2818|RK2808A|RK2918|RK3066)|RK2738|RK2808A',
303
- // http://www.fly-phone.com/devices/tablets/ ; http://www.fly-phone.com/service/
304
- 'FlyTablet' => 'IQ310|Fly Vision',
305
- // http://www.bqreaders.com/gb/tablets-prices-sale.html
306
- 'bqTablet' => 'Android.*(bq)?.*(Elcano|Curie|Edison|Maxwell|Kepler|Pascal|Tesla|Hypatia|Platon|Newton|Livingstone|Cervantes|Avant|Aquaris [E|M]10)|Maxwell.*Lite|Maxwell.*Plus',
307
- // http://www.huaweidevice.com/worldwide/productFamily.do?method=index&directoryId=5011&treeId=3290
308
- // http://www.huaweidevice.com/worldwide/downloadCenter.do?method=index&directoryId=3372&treeId=0&tb=1&type=software (including legacy tablets)
309
- 'HuaweiTablet' => 'MediaPad|MediaPad 7 Youth|IDEOS S7|S7-201c|S7-202u|S7-101|S7-103|S7-104|S7-105|S7-106|S7-201|S7-Slim',
310
- // Nec or Medias Tab
311
- 'NecTablet' => '\bN-06D|\bN-08D',
312
- // Pantech Tablets: http://www.pantechusa.com/phones/
313
- 'PantechTablet' => 'Pantech.*P4100',
314
- // Broncho Tablets: http://www.broncho.cn/ (hard to find)
315
- 'BronchoTablet' => 'Broncho.*(N701|N708|N802|a710)',
316
- // http://versusuk.com/support.html
317
- 'VersusTablet' => 'TOUCHPAD.*[78910]|\bTOUCHTAB\b',
318
- // http://www.zync.in/index.php/our-products/tablet-phablets
319
- 'ZyncTablet' => 'z1000|Z99 2G|z99|z930|z999|z990|z909|Z919|z900',
320
- // http://www.positivoinformatica.com.br/www/pessoal/tablet-ypy/
321
- 'PositivoTablet' => 'TB07STA|TB10STA|TB07FTA|TB10FTA',
322
- // https://www.nabitablet.com/
323
- 'NabiTablet' => 'Android.*\bNabi',
324
- 'KoboTablet' => 'Kobo Touch|\bK080\b|\bVox\b Build|\bArc\b Build',
325
- // French Danew Tablets http://www.danew.com/produits-tablette.php
326
- 'DanewTablet' => 'DSlide.*\b(700|701R|702|703R|704|802|970|971|972|973|974|1010|1012)\b',
327
- // Texet Tablets and Readers http://www.texet.ru/tablet/
328
- 'TexetTablet' => 'NaviPad|TB-772A|TM-7045|TM-7055|TM-9750|TM-7016|TM-7024|TM-7026|TM-7041|TM-7043|TM-7047|TM-8041|TM-9741|TM-9747|TM-9748|TM-9751|TM-7022|TM-7021|TM-7020|TM-7011|TM-7010|TM-7023|TM-7025|TM-7037W|TM-7038W|TM-7027W|TM-9720|TM-9725|TM-9737W|TM-1020|TM-9738W|TM-9740|TM-9743W|TB-807A|TB-771A|TB-727A|TB-725A|TB-719A|TB-823A|TB-805A|TB-723A|TB-715A|TB-707A|TB-705A|TB-709A|TB-711A|TB-890HD|TB-880HD|TB-790HD|TB-780HD|TB-770HD|TB-721HD|TB-710HD|TB-434HD|TB-860HD|TB-840HD|TB-760HD|TB-750HD|TB-740HD|TB-730HD|TB-722HD|TB-720HD|TB-700HD|TB-500HD|TB-470HD|TB-431HD|TB-430HD|TB-506|TB-504|TB-446|TB-436|TB-416|TB-146SE|TB-126SE',
329
- // Avoid detecting 'PLAYSTATION 3' as mobile.
330
- 'PlaystationTablet' => 'Playstation.*(Portable|Vita)',
331
- // http://www.trekstor.de/surftabs.html
332
- 'TrekstorTablet' => 'ST10416-1|VT10416-1|ST70408-1|ST702xx-1|ST702xx-2|ST80208|ST97216|ST70104-2|VT10416-2|ST10216-2A|SurfTab',
333
- // http://www.pyleaudio.com/Products.aspx?%2fproducts%2fPersonal-Electronics%2fTablets
334
- 'PyleAudioTablet' => '\b(PTBL10CEU|PTBL10C|PTBL72BC|PTBL72BCEU|PTBL7CEU|PTBL7C|PTBL92BC|PTBL92BCEU|PTBL9CEU|PTBL9CUK|PTBL9C)\b',
335
- // http://www.advandigital.com/index.php?link=content-product&jns=JP001
336
- // because of the short codenames we have to include whitespaces to reduce the possible conflicts.
337
- 'AdvanTablet' => 'Android.* \b(E3A|T3X|T5C|T5B|T3E|T3C|T3B|T1J|T1F|T2A|T1H|T1i|E1C|T1-E|T5-A|T4|E1-B|T2Ci|T1-B|T1-D|O1-A|E1-A|T1-A|T3A|T4i)\b ',
338
- // http://www.danytech.com/category/tablet-pc
339
- 'DanyTechTablet' => 'Genius Tab G3|Genius Tab S2|Genius Tab Q3|Genius Tab G4|Genius Tab Q4|Genius Tab G-II|Genius TAB GII|Genius TAB GIII|Genius Tab S1',
340
- // http://www.galapad.net/product.html
341
- 'GalapadTablet' => 'Android.*\bG1\b',
342
- // http://www.micromaxinfo.com/tablet/funbook
343
- 'MicromaxTablet' => 'Funbook|Micromax.*\b(P250|P560|P360|P362|P600|P300|P350|P500|P275)\b',
344
- // http://www.karbonnmobiles.com/products_tablet.php
345
- 'KarbonnTablet' => 'Android.*\b(A39|A37|A34|ST8|ST10|ST7|Smart Tab3|Smart Tab2)\b',
346
- // http://www.myallfine.com/Products.asp
347
- 'AllFineTablet' => 'Fine7 Genius|Fine7 Shine|Fine7 Air|Fine8 Style|Fine9 More|Fine10 Joy|Fine11 Wide',
348
- // http://www.proscanvideo.com/products-search.asp?itemClass=TABLET&itemnmbr=
349
- 'PROSCANTablet' => '\b(PEM63|PLT1023G|PLT1041|PLT1044|PLT1044G|PLT1091|PLT4311|PLT4311PL|PLT4315|PLT7030|PLT7033|PLT7033D|PLT7035|PLT7035D|PLT7044K|PLT7045K|PLT7045KB|PLT7071KG|PLT7072|PLT7223G|PLT7225G|PLT7777G|PLT7810K|PLT7849G|PLT7851G|PLT7852G|PLT8015|PLT8031|PLT8034|PLT8036|PLT8080K|PLT8082|PLT8088|PLT8223G|PLT8234G|PLT8235G|PLT8816K|PLT9011|PLT9045K|PLT9233G|PLT9735|PLT9760G|PLT9770G)\b',
350
- // http://www.yonesnav.com/products/products.php
351
- 'YONESTablet' => 'BQ1078|BC1003|BC1077|RK9702|BC9730|BC9001|IT9001|BC7008|BC7010|BC708|BC728|BC7012|BC7030|BC7027|BC7026',
352
- // http://www.cjshowroom.com/eproducts.aspx?classcode=004001001
353
- // China manufacturer makes tablets for different small brands (eg. http://www.zeepad.net/index.html)
354
- 'ChangJiaTablet' => 'TPC7102|TPC7103|TPC7105|TPC7106|TPC7107|TPC7201|TPC7203|TPC7205|TPC7210|TPC7708|TPC7709|TPC7712|TPC7110|TPC8101|TPC8103|TPC8105|TPC8106|TPC8203|TPC8205|TPC8503|TPC9106|TPC9701|TPC97101|TPC97103|TPC97105|TPC97106|TPC97111|TPC97113|TPC97203|TPC97603|TPC97809|TPC97205|TPC10101|TPC10103|TPC10106|TPC10111|TPC10203|TPC10205|TPC10503',
355
- // http://www.gloryunion.cn/products.asp
356
- // http://www.allwinnertech.com/en/apply/mobile.html
357
- // http://www.ptcl.com.pk/pd_content.php?pd_id=284 (EVOTAB)
358
- // @todo: Softwiner tablets?
359
- // aka. Cute or Cool tablets. Not sure yet, must research to avoid collisions.
360
- 'GUTablet' => 'TX-A1301|TX-M9002|Q702|kf026', // A12R|D75A|D77|D79|R83|A95|A106C|R15|A75|A76|D71|D72|R71|R73|R77|D82|R85|D92|A97|D92|R91|A10F|A77F|W71F|A78F|W78F|W81F|A97F|W91F|W97F|R16G|C72|C73E|K72|K73|R96G
361
- // http://www.pointofview-online.com/showroom.php?shop_mode=product_listing&category_id=118
362
- 'PointOfViewTablet' => 'TAB-P506|TAB-navi-7-3G-M|TAB-P517|TAB-P-527|TAB-P701|TAB-P703|TAB-P721|TAB-P731N|TAB-P741|TAB-P825|TAB-P905|TAB-P925|TAB-PR945|TAB-PL1015|TAB-P1025|TAB-PI1045|TAB-P1325|TAB-PROTAB[0-9]+|TAB-PROTAB25|TAB-PROTAB26|TAB-PROTAB27|TAB-PROTAB26XL|TAB-PROTAB2-IPS9|TAB-PROTAB30-IPS9|TAB-PROTAB25XXL|TAB-PROTAB26-IPS10|TAB-PROTAB30-IPS10',
363
- // http://www.overmax.pl/pl/katalog-produktow,p8/tablety,c14/
364
- // @todo: add more tests.
365
- 'OvermaxTablet' => 'OV-(SteelCore|NewBase|Basecore|Baseone|Exellen|Quattor|EduTab|Solution|ACTION|BasicTab|TeddyTab|MagicTab|Stream|TB-08|TB-09)',
366
- // http://hclmetablet.com/India/index.php
367
- 'HCLTablet' => 'HCL.*Tablet|Connect-3G-2.0|Connect-2G-2.0|ME Tablet U1|ME Tablet U2|ME Tablet G1|ME Tablet X1|ME Tablet Y2|ME Tablet Sync',
368
- // http://www.edigital.hu/Tablet_es_e-book_olvaso/Tablet-c18385.html
369
- 'DPSTablet' => 'DPS Dream 9|DPS Dual 7',
370
- // http://www.visture.com/index.asp
371
- 'VistureTablet' => 'V97 HD|i75 3G|Visture V4( HD)?|Visture V5( HD)?|Visture V10',
372
- // http://www.mijncresta.nl/tablet
373
- 'CrestaTablet' => 'CTP(-)?810|CTP(-)?818|CTP(-)?828|CTP(-)?838|CTP(-)?888|CTP(-)?978|CTP(-)?980|CTP(-)?987|CTP(-)?988|CTP(-)?989',
374
- // MediaTek - http://www.mediatek.com/_en/01_products/02_proSys.php?cata_sn=1&cata1_sn=1&cata2_sn=309
375
- 'MediatekTablet' => '\bMT8125|MT8389|MT8135|MT8377\b',
376
- // Concorde tab
377
- 'ConcordeTablet' => 'Concorde([ ]+)?Tab|ConCorde ReadMan',
378
- // GoClever Tablets - http://www.goclever.com/uk/products,c1/tablet,c5/
379
- 'GoCleverTablet' => 'GOCLEVER TAB|A7GOCLEVER|M1042|M7841|M742|R1042BK|R1041|TAB A975|TAB A7842|TAB A741|TAB A741L|TAB M723G|TAB M721|TAB A1021|TAB I921|TAB R721|TAB I720|TAB T76|TAB R70|TAB R76.2|TAB R106|TAB R83.2|TAB M813G|TAB I721|GCTA722|TAB I70|TAB I71|TAB S73|TAB R73|TAB R74|TAB R93|TAB R75|TAB R76.1|TAB A73|TAB A93|TAB A93.2|TAB T72|TAB R83|TAB R974|TAB R973|TAB A101|TAB A103|TAB A104|TAB A104.2|R105BK|M713G|A972BK|TAB A971|TAB R974.2|TAB R104|TAB R83.3|TAB A1042',
380
- // Modecom Tablets - http://www.modecom.eu/tablets/portal/
381
- 'ModecomTablet' => 'FreeTAB 9000|FreeTAB 7.4|FreeTAB 7004|FreeTAB 7800|FreeTAB 2096|FreeTAB 7.5|FreeTAB 1014|FreeTAB 1001 |FreeTAB 8001|FreeTAB 9706|FreeTAB 9702|FreeTAB 7003|FreeTAB 7002|FreeTAB 1002|FreeTAB 7801|FreeTAB 1331|FreeTAB 1004|FreeTAB 8002|FreeTAB 8014|FreeTAB 9704|FreeTAB 1003',
382
- // Vonino Tablets - http://www.vonino.eu/tablets
383
- 'VoninoTablet' => '\b(Argus[ _]?S|Diamond[ _]?79HD|Emerald[ _]?78E|Luna[ _]?70C|Onyx[ _]?S|Onyx[ _]?Z|Orin[ _]?HD|Orin[ _]?S|Otis[ _]?S|SpeedStar[ _]?S|Magnet[ _]?M9|Primus[ _]?94[ _]?3G|Primus[ _]?94HD|Primus[ _]?QS|Android.*\bQ8\b|Sirius[ _]?EVO[ _]?QS|Sirius[ _]?QS|Spirit[ _]?S)\b',
384
- // ECS Tablets - http://www.ecs.com.tw/ECSWebSite/Product/Product_Tablet_List.aspx?CategoryID=14&MenuID=107&childid=M_107&LanID=0
385
- 'ECSTablet' => 'V07OT2|TM105A|S10OT1|TR10CS1',
386
- // Storex Tablets - http://storex.fr/espace_client/support.html
387
- // @note: no need to add all the tablet codes since they are guided by the first regex.
388
- 'StorexTablet' => 'eZee[_\']?(Tab|Go)[0-9]+|TabLC7|Looney Tunes Tab',
389
- // Generic Vodafone tablets.
390
- 'VodafoneTablet' => 'SmartTab([ ]+)?[0-9]+|SmartTabII10|SmartTabII7|VF-1497',
391
- // French tablets - Essentiel B http://www.boulanger.fr/tablette_tactile_e-book/tablette_tactile_essentiel_b/cl_68908.htm?multiChoiceToDelete=brand&mc_brand=essentielb
392
- // Aka: http://www.essentielb.fr/
393
- 'EssentielBTablet' => 'Smart[ \']?TAB[ ]+?[0-9]+|Family[ \']?TAB2',
394
- // Ross & Moor - http://ross-moor.ru/
395
- 'RossMoorTablet' => 'RM-790|RM-997|RMD-878G|RMD-974R|RMT-705A|RMT-701|RME-601|RMT-501|RMT-711',
396
- // i-mobile http://product.i-mobilephone.com/Mobile_Device
397
- 'iMobileTablet' => 'i-mobile i-note',
398
- // http://www.tolino.de/de/vergleichen/
399
- 'TolinoTablet' => 'tolino tab [0-9.]+|tolino shine',
400
- // AudioSonic - a Kmart brand
401
- // http://www.kmart.com.au/webapp/wcs/stores/servlet/Search?langId=-1&storeId=10701&catalogId=10001&categoryId=193001&pageSize=72&currentPage=1&searchCategory=193001%2b4294965664&sortBy=p_MaxPrice%7c1
402
- 'AudioSonicTablet' => '\bC-22Q|T7-QC|T-17B|T-17P\b',
403
- // AMPE Tablets - http://www.ampe.com.my/product-category/tablets/
404
- // @todo: add them gradually to avoid conflicts.
405
- 'AMPETablet' => 'Android.* A78 ',
406
- // Skk Mobile - http://skkmobile.com.ph/product_tablets.php
407
- 'SkkTablet' => 'Android.* (SKYPAD|PHOENIX|CYCLOPS)',
408
- // Tecno Mobile (only tablet) - http://www.tecno-mobile.com/index.php/product?filterby=smart&list_order=all&page=1
409
- 'TecnoTablet' => 'TECNO P9',
410
- // JXD (consoles & tablets) - http://jxd.hk/products.asp?selectclassid=009008&clsid=3
411
- 'JXDTablet' => 'Android.* \b(F3000|A3300|JXD5000|JXD3000|JXD2000|JXD300B|JXD300|S5800|S7800|S602b|S5110b|S7300|S5300|S602|S603|S5100|S5110|S601|S7100a|P3000F|P3000s|P101|P200s|P1000m|P200m|P9100|P1000s|S6600b|S908|P1000|P300|S18|S6600|S9100)\b',
412
- // i-Joy tablets - http://www.i-joy.es/en/cat/products/tablets/
413
- 'iJoyTablet' => 'Tablet (Spirit 7|Essentia|Galatea|Fusion|Onix 7|Landa|Titan|Scooby|Deox|Stella|Themis|Argon|Unique 7|Sygnus|Hexen|Finity 7|Cream|Cream X2|Jade|Neon 7|Neron 7|Kandy|Scape|Saphyr 7|Rebel|Biox|Rebel|Rebel 8GB|Myst|Draco 7|Myst|Tab7-004|Myst|Tadeo Jones|Tablet Boing|Arrow|Draco Dual Cam|Aurix|Mint|Amity|Revolution|Finity 9|Neon 9|T9w|Amity 4GB Dual Cam|Stone 4GB|Stone 8GB|Andromeda|Silken|X2|Andromeda II|Halley|Flame|Saphyr 9,7|Touch 8|Planet|Triton|Unique 10|Hexen 10|Memphis 4GB|Memphis 8GB|Onix 10)',
414
- // http://www.intracon.eu/tablet
415
- 'FX2Tablet' => 'FX2 PAD7|FX2 PAD10',
416
- // http://www.xoro.de/produkte/
417
- // @note: Might be the same brand with 'Simply tablets'
418
- 'XoroTablet' => 'KidsPAD 701|PAD[ ]?712|PAD[ ]?714|PAD[ ]?716|PAD[ ]?717|PAD[ ]?718|PAD[ ]?720|PAD[ ]?721|PAD[ ]?722|PAD[ ]?790|PAD[ ]?792|PAD[ ]?900|PAD[ ]?9715D|PAD[ ]?9716DR|PAD[ ]?9718DR|PAD[ ]?9719QR|PAD[ ]?9720QR|TelePAD1030|Telepad1032|TelePAD730|TelePAD731|TelePAD732|TelePAD735Q|TelePAD830|TelePAD9730|TelePAD795|MegaPAD 1331|MegaPAD 1851|MegaPAD 2151',
419
- // http://www1.viewsonic.com/products/computing/tablets/
420
- 'ViewsonicTablet' => 'ViewPad 10pi|ViewPad 10e|ViewPad 10s|ViewPad E72|ViewPad7|ViewPad E100|ViewPad 7e|ViewSonic VB733|VB100a',
421
- // http://www.odys.de/web/internet-tablet_en.html
422
- 'OdysTablet' => 'LOOX|XENO10|ODYS[ -](Space|EVO|Xpress|NOON)|\bXELIO\b|Xelio10Pro|XELIO7PHONETAB|XELIO10EXTREME|XELIOPT2|NEO_QUAD10',
423
- // http://www.captiva-power.de/products.html#tablets-en
424
- 'CaptivaTablet' => 'CAPTIVA PAD',
425
- // IconBIT - http://www.iconbit.com/products/tablets/
426
- 'IconbitTablet' => 'NetTAB|NT-3702|NT-3702S|NT-3702S|NT-3603P|NT-3603P|NT-0704S|NT-0704S|NT-3805C|NT-3805C|NT-0806C|NT-0806C|NT-0909T|NT-0909T|NT-0907S|NT-0907S|NT-0902S|NT-0902S',
427
- // http://www.teclast.com/topic.php?channelID=70&topicID=140&pid=63
428
- 'TeclastTablet' => 'T98 4G|\bP80\b|\bX90HD\b|X98 Air|X98 Air 3G|\bX89\b|P80 3G|\bX80h\b|P98 Air|\bX89HD\b|P98 3G|\bP90HD\b|P89 3G|X98 3G|\bP70h\b|P79HD 3G|G18d 3G|\bP79HD\b|\bP89s\b|\bA88\b|\bP10HD\b|\bP19HD\b|G18 3G|\bP78HD\b|\bA78\b|\bP75\b|G17s 3G|G17h 3G|\bP85t\b|\bP90\b|\bP11\b|\bP98t\b|\bP98HD\b|\bG18d\b|\bP85s\b|\bP11HD\b|\bP88s\b|\bA80HD\b|\bA80se\b|\bA10h\b|\bP89\b|\bP78s\b|\bG18\b|\bP85\b|\bA70h\b|\bA70\b|\bG17\b|\bP18\b|\bA80s\b|\bA11s\b|\bP88HD\b|\bA80h\b|\bP76s\b|\bP76h\b|\bP98\b|\bA10HD\b|\bP78\b|\bP88\b|\bA11\b|\bA10t\b|\bP76a\b|\bP76t\b|\bP76e\b|\bP85HD\b|\bP85a\b|\bP86\b|\bP75HD\b|\bP76v\b|\bA12\b|\bP75a\b|\bA15\b|\bP76Ti\b|\bP81HD\b|\bA10\b|\bT760VE\b|\bT720HD\b|\bP76\b|\bP73\b|\bP71\b|\bP72\b|\bT720SE\b|\bC520Ti\b|\bT760\b|\bT720VE\b|T720-3GE|T720-WiFi',
429
- // Onda - http://www.onda-tablet.com/buy-android-onda.html?dir=desc&limit=all&order=price
430
- 'OndaTablet' => '\b(V975i|Vi30|VX530|V701|Vi60|V701s|Vi50|V801s|V719|Vx610w|VX610W|V819i|Vi10|VX580W|Vi10|V711s|V813|V811|V820w|V820|Vi20|V711|VI30W|V712|V891w|V972|V819w|V820w|Vi60|V820w|V711|V813s|V801|V819|V975s|V801|V819|V819|V818|V811|V712|V975m|V101w|V961w|V812|V818|V971|V971s|V919|V989|V116w|V102w|V973|Vi40)\b[\s]+',
431
- 'JaytechTablet' => 'TPC-PA762',
432
- 'BlaupunktTablet' => 'Endeavour 800NG|Endeavour 1010',
433
- // http://www.digma.ru/support/download/
434
- // @todo: Ebooks also (if requested)
435
- 'DigmaTablet' => '\b(iDx10|iDx9|iDx8|iDx7|iDxD7|iDxD8|iDsQ8|iDsQ7|iDsQ8|iDsD10|iDnD7|3TS804H|iDsQ11|iDj7|iDs10)\b',
436
- // http://www.evolioshop.com/ro/tablete-pc.html
437
- // http://www.evolio.ro/support/downloads_static.html?cat=2
438
- // @todo: Research some more
439
- 'EvolioTablet' => 'ARIA_Mini_wifi|Aria[ _]Mini|Evolio X10|Evolio X7|Evolio X8|\bEvotab\b|\bNeura\b',
440
- // @todo http://www.lavamobiles.com/tablets-data-cards
441
- 'LavaTablet' => 'QPAD E704|\bIvoryS\b|E-TAB IVORY|\bE-TAB\b',
442
- // http://www.breezetablet.com/
443
- 'AocTablet' => 'MW0811|MW0812|MW0922|MTK8382|MW1031|MW0831|MW0821|MW0931|MW0712',
444
- // http://www.mpmaneurope.com/en/products/internet-tablets-14/android-tablets-14/
445
- 'MpmanTablet' => 'MP11 OCTA|MP10 OCTA|MPQC1114|MPQC1004|MPQC994|MPQC974|MPQC973|MPQC804|MPQC784|MPQC780|\bMPG7\b|MPDCG75|MPDCG71|MPDC1006|MP101DC|MPDC9000|MPDC905|MPDC706HD|MPDC706|MPDC705|MPDC110|MPDC100|MPDC99|MPDC97|MPDC88|MPDC8|MPDC77|MP709|MID701|MID711|MID170|MPDC703|MPQC1010',
446
- // https://www.celkonmobiles.com/?_a=categoryphones&sid=2
447
- 'CelkonTablet' => 'CT695|CT888|CT[\s]?910|CT7 Tab|CT9 Tab|CT3 Tab|CT2 Tab|CT1 Tab|C820|C720|\bCT-1\b',
448
- // http://www.wolderelectronics.com/productos/manuales-y-guias-rapidas/categoria-2-miTab
449
- 'WolderTablet' => 'miTab \b(DIAMOND|SPACE|BROOKLYN|NEO|FLY|MANHATTAN|FUNK|EVOLUTION|SKY|GOCAR|IRON|GENIUS|POP|MINT|EPSILON|BROADWAY|JUMP|HOP|LEGEND|NEW AGE|LINE|ADVANCE|FEEL|FOLLOW|LIKE|LINK|LIVE|THINK|FREEDOM|CHICAGO|CLEVELAND|BALTIMORE-GH|IOWA|BOSTON|SEATTLE|PHOENIX|DALLAS|IN 101|MasterChef)\b',
450
- // http://www.mi.com/en
451
- 'MiTablet' => '\bMI PAD\b|\bHM NOTE 1W\b',
452
- // http://www.nbru.cn/index.html
453
- 'NibiruTablet' => 'Nibiru M1|Nibiru Jupiter One',
454
- // http://navroad.com/products/produkty/tablety/
455
- 'NexoTablet' => 'NEXO NOVA|NEXO 10|NEXO AVIO|NEXO FREE|NEXO GO|NEXO EVO|NEXO 3G|NEXO SMART|NEXO KIDDO|NEXO MOBI',
456
- // http://leader-online.com/new_site/product-category/tablets/
457
- // http://www.leader-online.net.au/List/Tablet
458
- 'LeaderTablet' => 'TBLT10Q|TBLT10I|TBL-10WDKB|TBL-10WDKBO2013|TBL-W230V2|TBL-W450|TBL-W500|SV572|TBLT7I|TBA-AC7-8G|TBLT79|TBL-8W16|TBL-10W32|TBL-10WKB|TBL-W100',
459
- // http://www.datawind.com/ubislate/
460
- 'UbislateTablet' => 'UbiSlate[\s]?7C',
461
- // http://www.pocketbook-int.com/ru/support
462
- 'PocketBookTablet' => 'Pocketbook',
463
- // http://www.kocaso.com/product_tablet.html
464
- 'KocasoTablet' => '\b(TB-1207)\b',
465
- // http://global.hisense.com/product/asia/tablet/Sero7/201412/t20141215_91832.htm
466
- 'HisenseTablet' => '\b(F5281|E2371)\b',
467
- // http://www.tesco.com/direct/hudl/
468
- 'Hudl' => 'Hudl HT7S3|Hudl 2',
469
- // http://www.telstra.com.au/home-phone/thub-2/
470
- 'TelstraTablet' => 'T-Hub2',
471
- 'GenericTablet' => 'Android.*\b97D\b|Tablet(?!.*PC)|BNTV250A|MID-WCDMA|LogicPD Zoom2|\bA7EB\b|CatNova8|A1_07|CT704|CT1002|\bM721\b|rk30sdk|\bEVOTAB\b|M758A|ET904|ALUMIUM10|Smartfren Tab|Endeavour 1010|Tablet-PC-4|Tagi Tab|\bM6pro\b|CT1020W|arc 10HD|\bTP750\b'
472
- );
473
-
474
- /**
475
- * List of mobile Operating Systems.
476
- *
477
- * @var array
478
- */
479
- protected static $operatingSystems = array(
480
- 'AndroidOS' => 'Android',
481
- 'BlackBerryOS' => 'blackberry|\bBB10\b|rim tablet os',
482
- 'PalmOS' => 'PalmOS|avantgo|blazer|elaine|hiptop|palm|plucker|xiino',
483
- 'SymbianOS' => 'Symbian|SymbOS|Series60|Series40|SYB-[0-9]+|\bS60\b',
484
- // @reference: http://en.wikipedia.org/wiki/Windows_Mobile
485
- 'WindowsMobileOS' => 'Windows CE.*(PPC|Smartphone|Mobile|[0-9]{3}x[0-9]{3})|Window Mobile|Windows Phone [0-9.]+|WCE;',
486
- // @reference: http://en.wikipedia.org/wiki/Windows_Phone
487
- // http://wifeng.cn/?r=blog&a=view&id=106
488
- // http://nicksnettravels.builttoroam.com/post/2011/01/10/Bogus-Windows-Phone-7-User-Agent-String.aspx
489
- // http://msdn.microsoft.com/library/ms537503.aspx
490
- // https://msdn.microsoft.com/en-us/library/hh869301(v=vs.85).aspx
491
- 'WindowsPhoneOS' => 'Windows Phone 10.0|Windows Phone 8.1|Windows Phone 8.0|Windows Phone OS|XBLWP7|ZuneWP7|Windows NT 6.[23]; ARM;',
492
- 'iOS' => '\biPhone.*Mobile|\biPod|\biPad',
493
- // http://en.wikipedia.org/wiki/MeeGo
494
- // @todo: research MeeGo in UAs
495
- 'MeeGoOS' => 'MeeGo',
496
- // http://en.wikipedia.org/wiki/Maemo
497
- // @todo: research Maemo in UAs
498
- 'MaemoOS' => 'Maemo',
499
- 'JavaOS' => 'J2ME/|\bMIDP\b|\bCLDC\b', // '|Java/' produces bug #135
500
- 'webOS' => 'webOS|hpwOS',
501
- 'badaOS' => '\bBada\b',
502
- 'BREWOS' => 'BREW',
503
- );
504
-
505
- /**
506
- * List of mobile User Agents.
507
- *
508
- * IMPORTANT: This is a list of only mobile browsers.
509
- * Mobile Detect 2.x supports only mobile browsers,
510
- * it was never designed to detect all browsers.
511
- * The change will come in 2017 in the 3.x release for PHP7.
512
- *
513
- * @var array
514
- */
515
- protected static $browsers = array(
516
- //'Vivaldi' => 'Vivaldi',
517
- // @reference: https://developers.google.com/chrome/mobile/docs/user-agent
518
- 'Chrome' => '\bCrMo\b|CriOS|Android.*Chrome/[.0-9]* (Mobile)?',
519
- 'Dolfin' => '\bDolfin\b',
520
- 'Opera' => 'Opera.*Mini|Opera.*Mobi|Android.*Opera|Mobile.*OPR/[0-9.]+|Coast/[0-9.]+',
521
- 'Skyfire' => 'Skyfire',
522
- 'Edge' => 'Mobile Safari/[.0-9]* Edge',
523
- 'IE' => 'IEMobile|MSIEMobile', // |Trident/[.0-9]+
524
- 'Firefox' => 'fennec|firefox.*maemo|(Mobile|Tablet).*Firefox|Firefox.*Mobile|FxiOS',
525
- 'Bolt' => 'bolt',
526
- 'TeaShark' => 'teashark',
527
- 'Blazer' => 'Blazer',
528
- // @reference: http://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariWebContent/OptimizingforSafarioniPhone/OptimizingforSafarioniPhone.html#//apple_ref/doc/uid/TP40006517-SW3
529
- 'Safari' => 'Version.*Mobile.*Safari|Safari.*Mobile|MobileSafari',
530
- // http://en.wikipedia.org/wiki/Midori_(web_browser)
531
- //'Midori' => 'midori',
532
- //'Tizen' => 'Tizen',
533
- 'UCBrowser' => 'UC.*Browser|UCWEB',
534
- 'baiduboxapp' => 'baiduboxapp',
535
- 'baidubrowser' => 'baidubrowser',
536
- // https://github.com/serbanghita/Mobile-Detect/issues/7
537
- 'DiigoBrowser' => 'DiigoBrowser',
538
- // http://www.puffinbrowser.com/index.php
539
- 'Puffin' => 'Puffin',
540
- // http://mercury-browser.com/index.html
541
- 'Mercury' => '\bMercury\b',
542
- // http://en.wikipedia.org/wiki/Obigo_Browser
543
- 'ObigoBrowser' => 'Obigo',
544
- // http://en.wikipedia.org/wiki/NetFront
545
- 'NetFront' => 'NF-Browser',
546
- // @reference: http://en.wikipedia.org/wiki/Minimo
547
- // http://en.wikipedia.org/wiki/Vision_Mobile_Browser
548
- 'GenericBrowser' => 'NokiaBrowser|OviBrowser|OneBrowser|TwonkyBeamBrowser|SEMC.*Browser|FlyFlow|Minimo|NetFront|Novarra-Vision|MQQBrowser|MicroMessenger',
549
- // @reference: https://en.wikipedia.org/wiki/Pale_Moon_(web_browser)
550
- 'PaleMoon' => 'Android.*PaleMoon|Mobile.*PaleMoon',
551
- );
552
-
553
- /**
554
- * Utilities.
555
- *
556
- * @var array
557
- */
558
- protected static $utilities = array(
559
- // Experimental. When a mobile device wants to switch to 'Desktop Mode'.
560
- // http://scottcate.com/technology/windows-phone-8-ie10-desktop-or-mobile/
561
- // https://github.com/serbanghita/Mobile-Detect/issues/57#issuecomment-15024011
562
- // https://developers.facebook.com/docs/sharing/best-practices
563
- 'Bot' => 'Googlebot|facebookexternalhit|AdsBot-Google|Google Keyword Suggestion|Facebot|YandexBot|YandexMobileBot|bingbot|ia_archiver|AhrefsBot|Ezooms|GSLFbot|WBSearchBot|Twitterbot|TweetmemeBot|Twikle|PaperLiBot|Wotbox|UnwindFetchor|Exabot|MJ12bot|YandexImages|TurnitinBot|Pingdom',
564
- 'MobileBot' => 'Googlebot-Mobile|AdsBot-Google-Mobile|YahooSeeker/M1A1-R2D2',
565
- 'DesktopMode' => 'WPDesktop',
566
- 'TV' => 'SonyDTV|HbbTV', // experimental
567
- 'WebKit' => '(webkit)[ /]([\w.]+)',
568
- // @todo: Include JXD consoles.
569
- 'Console' => '\b(Nintendo|Nintendo WiiU|Nintendo 3DS|PLAYSTATION|Xbox)\b',
570
- 'Watch' => 'SM-V700',
571
- );
572
-
573
- /**
574
- * All possible HTTP headers that represent the
575
- * User-Agent string.
576
- *
577
- * @var array
578
- */
579
- protected static $uaHttpHeaders = array(
580
- // The default User-Agent string.
581
- 'HTTP_USER_AGENT',
582
- // Header can occur on devices using Opera Mini.
583
- 'HTTP_X_OPERAMINI_PHONE_UA',
584
- // Vodafone specific header: http://www.seoprinciple.com/mobile-web-community-still-angry-at-vodafone/24/
585
- 'HTTP_X_DEVICE_USER_AGENT',
586
- 'HTTP_X_ORIGINAL_USER_AGENT',
587
- 'HTTP_X_SKYFIRE_PHONE',
588
- 'HTTP_X_BOLT_PHONE_UA',
589
- 'HTTP_DEVICE_STOCK_UA',
590
- 'HTTP_X_UCBROWSER_DEVICE_UA'
591
- );
592
-
593
- /**
594
- * The individual segments that could exist in a User-Agent string. VER refers to the regular
595
- * expression defined in the constant self::VER.
596
- *
597
- * @var array
598
- */
599
- protected static $properties = array(
600
-
601
- // Build
602
- 'Mobile' => 'Mobile/[VER]',
603
- 'Build' => 'Build/[VER]',
604
- 'Version' => 'Version/[VER]',
605
- 'VendorID' => 'VendorID/[VER]',
606
-
607
- // Devices
608
- 'iPad' => 'iPad.*CPU[a-z ]+[VER]',
609
- 'iPhone' => 'iPhone.*CPU[a-z ]+[VER]',
610
- 'iPod' => 'iPod.*CPU[a-z ]+[VER]',
611
- //'BlackBerry' => array('BlackBerry[VER]', 'BlackBerry [VER];'),
612
- 'Kindle' => 'Kindle/[VER]',
613
-
614
- // Browser
615
- 'Chrome' => array('Chrome/[VER]', 'CriOS/[VER]', 'CrMo/[VER]'),
616
- 'Coast' => array('Coast/[VER]'),
617
- 'Dolfin' => 'Dolfin/[VER]',
618
- // @reference: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent/Firefox
619
- 'Firefox' => array('Firefox/[VER]', 'FxiOS/[VER]'),
620
- 'Fennec' => 'Fennec/[VER]',
621
- // http://msdn.microsoft.com/en-us/library/ms537503(v=vs.85).aspx
622
- // https://msdn.microsoft.com/en-us/library/ie/hh869301(v=vs.85).aspx
623
- 'Edge' => 'Edge/[VER]',
624
- 'IE' => array('IEMobile/[VER];', 'IEMobile [VER]', 'MSIE [VER];', 'Trident/[0-9.]+;.*rv:[VER]'),
625
- // http://en.wikipedia.org/wiki/NetFront
626
- 'NetFront' => 'NetFront/[VER]',
627
- 'NokiaBrowser' => 'NokiaBrowser/[VER]',
628
- 'Opera' => array( ' OPR/[VER]', 'Opera Mini/[VER]', 'Version/[VER]' ),
629
- 'Opera Mini' => 'Opera Mini/[VER]',
630
- 'Opera Mobi' => 'Version/[VER]',
631
- 'UC Browser' => 'UC Browser[VER]',
632
- 'MQQBrowser' => 'MQQBrowser/[VER]',
633
- 'MicroMessenger' => 'MicroMessenger/[VER]',
634
- 'baiduboxapp' => 'baiduboxapp/[VER]',
635
- 'baidubrowser' => 'baidubrowser/[VER]',
636
- 'SamsungBrowser' => 'SamsungBrowser/[VER]',
637
- 'Iron' => 'Iron/[VER]',
638
- // @note: Safari 7534.48.3 is actually Version 5.1.
639
- // @note: On BlackBerry the Version is overwriten by the OS.
640
- 'Safari' => array( 'Version/[VER]', 'Safari/[VER]' ),
641
- 'Skyfire' => 'Skyfire/[VER]',
642
- 'Tizen' => 'Tizen/[VER]',
643
- 'Webkit' => 'webkit[ /][VER]',
644
- 'PaleMoon' => 'PaleMoon/[VER]',
645
-
646
- // Engine
647
- 'Gecko' => 'Gecko/[VER]',
648
- 'Trident' => 'Trident/[VER]',
649
- 'Presto' => 'Presto/[VER]',
650
- 'Goanna' => 'Goanna/[VER]',
651
-
652
- // OS
653
- 'iOS' => ' \bi?OS\b [VER][ ;]{1}',
654
- 'Android' => 'Android [VER]',
655
- 'BlackBerry' => array('BlackBerry[\w]+/[VER]', 'BlackBerry.*Version/[VER]', 'Version/[VER]'),
656
- 'BREW' => 'BREW [VER]',
657
- 'Java' => 'Java/[VER]',
658
- // @reference: http://windowsteamblog.com/windows_phone/b/wpdev/archive/2011/08/29/introducing-the-ie9-on-windows-phone-mango-user-agent-string.aspx
659
- // @reference: http://en.wikipedia.org/wiki/Windows_NT#Releases
660
- 'Windows Phone OS' => array( 'Windows Phone OS [VER]', 'Windows Phone [VER]'),
661
- 'Windows Phone' => 'Windows Phone [VER]',
662
- 'Windows CE' => 'Windows CE/[VER]',
663
- // http://social.msdn.microsoft.com/Forums/en-US/windowsdeveloperpreviewgeneral/thread/6be392da-4d2f-41b4-8354-8dcee20c85cd
664
- 'Windows NT' => 'Windows NT [VER]',
665
- 'Symbian' => array('SymbianOS/[VER]', 'Symbian/[VER]'),
666
- 'webOS' => array('webOS/[VER]', 'hpwOS/[VER];'),
667
- );
668
-
669
- /**
670
- * Construct an instance of this class.
671
- *
672
- * @param array $headers Specify the headers as injection. Should be PHP _SERVER flavored.
673
- * If left empty, will use the global _SERVER['HTTP_*'] vars instead.
674
- * @param string $userAgent Inject the User-Agent header. If null, will use HTTP_USER_AGENT
675
- * from the $headers array instead.
676
- */
677
- public function __construct(
678
- array $headers = null,
679
- $userAgent = null
680
- ) {
681
- $this->setHttpHeaders($headers);
682
- $this->setUserAgent($userAgent);
683
- }
684
-
685
- /**
686
- * Get the current script version.
687
- * This is useful for the demo.php file,
688
- * so people can check on what version they are testing
689
- * for mobile devices.
690
- *
691
- * @return string The version number in semantic version format.
692
- */
693
- public static function getScriptVersion()
694
- {
695
- return self::VERSION;
696
- }
697
-
698
- /**
699
- * Set the HTTP Headers. Must be PHP-flavored. This method will reset existing headers.
700
- *
701
- * @param array $httpHeaders The headers to set. If null, then using PHP's _SERVER to extract
702
- * the headers. The default null is left for backwards compatibility.
703
- */
704
- public function setHttpHeaders($httpHeaders = null)
705
- {
706
- // use global _SERVER if $httpHeaders aren't defined
707
- if (!is_array($httpHeaders) || !count($httpHeaders)) {
708
- $httpHeaders = $_SERVER;
709
- }
710
-
711
- // clear existing headers
712
- $this->httpHeaders = array();
713
-
714
- // Only save HTTP headers. In PHP land, that means only _SERVER vars that
715
- // start with HTTP_.
716
- foreach ($httpHeaders as $key => $value) {
717
- if (substr($key, 0, 5) === 'HTTP_') {
718
- $this->httpHeaders[$key] = $value;
719
- }
720
- }
721
-
722
- // In case we're dealing with CloudFront, we need to know.
723
- $this->setCfHeaders($httpHeaders);
724
- }
725
-
726
- /**
727
- * Retrieves the HTTP headers.
728
- *
729
- * @return array
730
- */
731
- public function getHttpHeaders()
732
- {
733
- return $this->httpHeaders;
734
- }
735
-
736
- /**
737
- * Retrieves a particular header. If it doesn't exist, no exception/error is caused.
738
- * Simply null is returned.
739
- *
740
- * @param string $header The name of the header to retrieve. Can be HTTP compliant such as
741
- * "User-Agent" or "X-Device-User-Agent" or can be php-esque with the
742
- * all-caps, HTTP_ prefixed, underscore seperated awesomeness.
743
- *
744
- * @return string|null The value of the header.
745
- */
746
- public function getHttpHeader($header)
747
- {
748
- // are we using PHP-flavored headers?
749
- if (strpos($header, '_') === false) {
750
- $header = str_replace('-', '_', $header);
751
- $header = strtoupper($header);
752
- }
753
-
754
- // test the alternate, too
755
- $altHeader = 'HTTP_' . $header;
756
-
757
- //Test both the regular and the HTTP_ prefix
758
- if (isset($this->httpHeaders[$header])) {
759
- return $this->httpHeaders[$header];
760
- } elseif (isset($this->httpHeaders[$altHeader])) {
761
- return $this->httpHeaders[$altHeader];
762
- }
763
-
764
- return null;
765
- }
766
-
767
- public function getMobileHeaders()
768
- {
769
- return self::$mobileHeaders;
770
- }
771
-
772
- /**
773
- * Get all possible HTTP headers that
774
- * can contain the User-Agent string.
775
- *
776
- * @return array List of HTTP headers.
777
- */
778
- public function getUaHttpHeaders()
779
- {
780
- return self::$uaHttpHeaders;
781
- }
782
-
783
-
784
- /**
785
- * Set CloudFront headers
786
- * http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/header-caching.html#header-caching-web-device
787
- *
788
- * @param array $cfHeaders List of HTTP headers
789
- *
790
- * @return boolean If there were CloudFront headers to be set
791
- */
792
- public function setCfHeaders($cfHeaders = null) {
793
- // use global _SERVER if $cfHeaders aren't defined
794
- if (!is_array($cfHeaders) || !count($cfHeaders)) {
795
- $cfHeaders = $_SERVER;
796
- }
797
-
798
- // clear existing headers
799
- $this->cloudfrontHeaders = array();
800
-
801
- // Only save CLOUDFRONT headers. In PHP land, that means only _SERVER vars that
802
- // start with cloudfront-.
803
- $response = false;
804
- foreach ($cfHeaders as $key => $value) {
805
- if (substr(strtolower($key), 0, 16) === 'http_cloudfront_') {
806
- $this->cloudfrontHeaders[strtoupper($key)] = $value;
807
- $response = true;
808
- }
809
- }
810
-
811
- return $response;
812
- }
813
-
814
- /**
815
- * Retrieves the cloudfront headers.
816
- *
817
- * @return array
818
- */
819
- public function getCfHeaders()
820
- {
821
- return $this->cloudfrontHeaders;
822
- }
823
-
824
- /**
825
- * Set the User-Agent to be used.
826
- *
827
- * @param string $userAgent The user agent string to set.
828
- *
829
- * @return string|null
830
- */
831
- public function setUserAgent($userAgent = null)
832
- {
833
- // Invalidate cache due to #375
834
- $this->cache = array();
835
-
836
- if (false === empty($userAgent)) {
837
- return $this->userAgent = $userAgent;
838
- } else {
839
- $this->userAgent = null;
840
- foreach ($this->getUaHttpHeaders() as $altHeader) {
841
- if (false === empty($this->httpHeaders[$altHeader])) { // @todo: should use getHttpHeader(), but it would be slow. (Serban)
842
- $this->userAgent .= $this->httpHeaders[$altHeader] . " ";
843
- }
844
- }
845
-
846
- if (!empty($this->userAgent)) {
847
- return $this->userAgent = trim($this->userAgent);
848
- }
849
- }
850
-
851
- if (count($this->getCfHeaders()) > 0) {
852
- return $this->userAgent = 'Amazon CloudFront';
853
- }
854
- return $this->userAgent = null;
855
- }
856
-
857
- /**
858
- * Retrieve the User-Agent.
859
- *
860
- * @return string|null The user agent if it's set.
861
- */
862
- public function getUserAgent()
863
- {
864
- return $this->userAgent;
865
- }
866
-
867
- /**
868
- * Set the detection type. Must be one of self::DETECTION_TYPE_MOBILE or
869
- * self::DETECTION_TYPE_EXTENDED. Otherwise, nothing is set.
870
- *
871
- * @deprecated since version 2.6.9
872
- *
873
- * @param string $type The type. Must be a self::DETECTION_TYPE_* constant. The default
874
- * parameter is null which will default to self::DETECTION_TYPE_MOBILE.
875
- */
876
- public function setDetectionType($type = null)
877
- {
878
- if ($type === null) {
879
- $type = self::DETECTION_TYPE_MOBILE;
880
- }
881
-
882
- if ($type !== self::DETECTION_TYPE_MOBILE && $type !== self::DETECTION_TYPE_EXTENDED) {
883
- return;
884
- }
885
-
886
- $this->detectionType = $type;
887
- }
888
-
889
- public function getMatchingRegex()
890
- {
891
- return $this->matchingRegex;
892
- }
893
-
894
- public function getMatchesArray()
895
- {
896
- return $this->matchesArray;
897
- }
898
-
899
- /**
900
- * Retrieve the list of known phone devices.
901
- *
902
- * @return array List of phone devices.
903
- */
904
- public static function getPhoneDevices()
905
- {
906
- return self::$phoneDevices;
907
- }
908
-
909
- /**
910
- * Retrieve the list of known tablet devices.
911
- *
912
- * @return array List of tablet devices.
913
- */
914
- public static function getTabletDevices()
915
- {
916
- return self::$tabletDevices;
917
- }
918
-
919
- /**
920
- * Alias for getBrowsers() method.
921
- *
922
- * @return array List of user agents.
923
- */
924
- public static function getUserAgents()
925
- {
926
- return self::getBrowsers();
927
- }
928
-
929
- /**
930
- * Retrieve the list of known browsers. Specifically, the user agents.
931
- *
932
- * @return array List of browsers / user agents.
933
- */
934
- public static function getBrowsers()
935
- {
936
- return self::$browsers;
937
- }
938
-
939
- /**
940
- * Retrieve the list of known utilities.
941
- *
942
- * @return array List of utilities.
943
- */
944
- public static function getUtilities()
945
- {
946
- return self::$utilities;
947
- }
948
-
949
- /**
950
- * Method gets the mobile detection rules. This method is used for the magic methods $detect->is*().
951
- *
952
- * @deprecated since version 2.6.9
953
- *
954
- * @return array All the rules (but not extended).
955
- */
956
- public static function getMobileDetectionRules()
957
- {
958
- static $rules;
959
-
960
- if (!$rules) {
961
- $rules = array_merge(
962
- self::$phoneDevices,
963
- self::$tabletDevices,
964
- self::$operatingSystems,
965
- self::$browsers
966
- );
967
- }
968
-
969
- return $rules;
970
-
971
- }
972
-
973
- /**
974
- * Method gets the mobile detection rules + utilities.
975
- * The reason this is separate is because utilities rules
976
- * don't necessary imply mobile. This method is used inside
977
- * the new $detect->is('stuff') method.
978
- *
979
- * @deprecated since version 2.6.9
980
- *
981
- * @return array All the rules + extended.
982
- */
983
- public function getMobileDetectionRulesExtended()
984
- {
985
- static $rules;
986
-
987
- if (!$rules) {
988
- // Merge all rules together.
989
- $rules = array_merge(
990
- self::$phoneDevices,
991
- self::$tabletDevices,
992
- self::$operatingSystems,
993
- self::$browsers,
994
- self::$utilities
995
- );
996
- }
997
-
998
- return $rules;
999
- }
1000
-
1001
- /**
1002
- * Retrieve the current set of rules.
1003
- *
1004
- * @deprecated since version 2.6.9
1005
- *
1006
- * @return array
1007
- */
1008
- public function getRules()
1009
- {
1010
- if ($this->detectionType == self::DETECTION_TYPE_EXTENDED) {
1011
- return self::getMobileDetectionRulesExtended();
1012
- } else {
1013
- return self::getMobileDetectionRules();
1014
- }
1015
- }
1016
-
1017
- /**
1018
- * Retrieve the list of mobile operating systems.
1019
- *
1020
- * @return array The list of mobile operating systems.
1021
- */
1022
- public static function getOperatingSystems()
1023
- {
1024
- return self::$operatingSystems;
1025
- }
1026
-
1027
- /**
1028
- * Check the HTTP headers for signs of mobile.
1029
- * This is the fastest mobile check possible; it's used
1030
- * inside isMobile() method.
1031
- *
1032
- * @return bool
1033
- */
1034
- public function checkHttpHeadersForMobile()
1035
- {
1036
-
1037
- foreach ($this->getMobileHeaders() as $mobileHeader => $matchType) {
1038
- if (isset($this->httpHeaders[$mobileHeader])) {
1039
- if (is_array($matchType['matches'])) {
1040
- foreach ($matchType['matches'] as $_match) {
1041
- if (strpos($this->httpHeaders[$mobileHeader], $_match) !== false) {
1042
- return true;
1043
- }
1044
- }
1045
-
1046
- return false;
1047
- } else {
1048
- return true;
1049
- }
1050
- }
1051
- }
1052
-
1053
- return false;
1054
-
1055
- }
1056
-
1057
- /**
1058
- * Magic overloading method.
1059
- *
1060
- * @method boolean is[...]()
1061
- * @param string $name
1062
- * @param array $arguments
1063
- * @return mixed
1064
- * @throws BadMethodCallException when the method doesn't exist and doesn't start with 'is'
1065
- */
1066
- public function __call($name, $arguments)
1067
- {
1068
- // make sure the name starts with 'is', otherwise
1069
- if (substr($name, 0, 2) !== 'is') {
1070
- throw new BadMethodCallException("No such method exists: $name");
1071
- }
1072
-
1073
- $this->setDetectionType(self::DETECTION_TYPE_MOBILE);
1074
-
1075
- $key = substr($name, 2);
1076
-
1077
- return $this->matchUAAgainstKey($key);
1078
- }
1079
-
1080
- /**
1081
- * Find a detection rule that matches the current User-agent.
1082
- *
1083
- * @param null $userAgent deprecated
1084
- * @return boolean
1085
- */
1086
- protected function matchDetectionRulesAgainstUA($userAgent = null)
1087
- {
1088
- // Begin general search.
1089
- foreach ($this->getRules() as $_regex) {
1090
- if (empty($_regex)) {
1091
- continue;
1092
- }
1093
-
1094
- if ($this->match($_regex, $userAgent)) {
1095
- return true;
1096
- }
1097
- }
1098
-
1099
- return false;
1100
- }
1101
-
1102
- /**
1103
- * Search for a certain key in the rules array.
1104
- * If the key is found then try to match the corresponding
1105
- * regex against the User-Agent.
1106
- *
1107
- * @param string $key
1108
- *
1109
- * @return boolean
1110
- */
1111
- protected function matchUAAgainstKey($key)
1112
- {
1113
- // Make the keys lowercase so we can match: isIphone(), isiPhone(), isiphone(), etc.
1114
- $key = strtolower($key);
1115
- if (false === isset($this->cache[$key])) {
1116
-
1117
- // change the keys to lower case
1118
- $_rules = array_change_key_case($this->getRules());
1119
-
1120
- if (false === empty($_rules[$key])) {
1121
- $this->cache[$key] = $this->match($_rules[$key]);
1122
- }
1123
-
1124
- if (false === isset($this->cache[$key])) {
1125
- $this->cache[$key] = false;
1126
- }
1127
- }
1128
-
1129
- return $this->cache[$key];
1130
- }
1131
-
1132
- /**
1133
- * Check if the device is mobile.
1134
- * Returns true if any type of mobile device detected, including special ones
1135
- * @param null $userAgent deprecated
1136
- * @param null $httpHeaders deprecated
1137
- * @return bool
1138
- */
1139
- public function isMobile($userAgent = null, $httpHeaders = null)
1140
- {
1141
-
1142
- if ($httpHeaders) {
1143
- $this->setHttpHeaders($httpHeaders);
1144
- }
1145
-
1146
- if ($userAgent) {
1147
- $this->setUserAgent($userAgent);
1148
- }
1149
-
1150
- // Check specifically for cloudfront headers if the useragent === 'Amazon CloudFront'
1151
- if ($this->getUserAgent() === 'Amazon CloudFront') {
1152
- $cfHeaders = $this->getCfHeaders();
1153
- if(array_key_exists('HTTP_CLOUDFRONT_IS_MOBILE_VIEWER', $cfHeaders) && $cfHeaders['HTTP_CLOUDFRONT_IS_MOBILE_VIEWER'] === 'true') {
1154
- return true;
1155
- }
1156
- }
1157
-
1158
- $this->setDetectionType(self::DETECTION_TYPE_MOBILE);
1159
-
1160
- if ($this->checkHttpHeadersForMobile()) {
1161
- return true;
1162
- } else {
1163
- return $this->matchDetectionRulesAgainstUA();
1164
- }
1165
-
1166
- }
1167
-
1168
- /**
1169
- * Check if the device is a tablet.
1170
- * Return true if any type of tablet device is detected.
1171
- *
1172
- * @param string $userAgent deprecated
1173
- * @param array $httpHeaders deprecated
1174
- * @return bool
1175
- */
1176
- public function isTablet($userAgent = null, $httpHeaders = null)
1177
- {
1178
- // Check specifically for cloudfront headers if the useragent === 'Amazon CloudFront'
1179
- if ($this->getUserAgent() === 'Amazon CloudFront') {
1180
- $cfHeaders = $this->getCfHeaders();
1181
- if(array_key_exists('HTTP_CLOUDFRONT_IS_TABLET_VIEWER', $cfHeaders) && $cfHeaders['HTTP_CLOUDFRONT_IS_TABLET_VIEWER'] === 'true') {
1182
- return true;
1183
- }
1184
- }
1185
-
1186
- $this->setDetectionType(self::DETECTION_TYPE_MOBILE);
1187
-
1188
- foreach (self::$tabletDevices as $_regex) {
1189
- if ($this->match($_regex, $userAgent)) {
1190
- return true;
1191
- }
1192
- }
1193
-
1194
- return false;
1195
- }
1196
-
1197
- /**
1198
- * This method checks for a certain property in the
1199
- * userAgent.
1200
- * @todo: The httpHeaders part is not yet used.
1201
- *
1202
- * @param string $key
1203
- * @param string $userAgent deprecated
1204
- * @param string $httpHeaders deprecated
1205
- * @return bool|int|null
1206
- */
1207
- public function is($key, $userAgent = null, $httpHeaders = null)
1208
- {
1209
- // Set the UA and HTTP headers only if needed (eg. batch mode).
1210
- if ($httpHeaders) {
1211
- $this->setHttpHeaders($httpHeaders);
1212
- }
1213
-
1214
- if ($userAgent) {
1215
- $this->setUserAgent($userAgent);
1216
- }
1217
-
1218
- $this->setDetectionType(self::DETECTION_TYPE_EXTENDED);
1219
-
1220
- return $this->matchUAAgainstKey($key);
1221
- }
1222
-
1223
- /**
1224
- * Some detection rules are relative (not standard),
1225
- * because of the diversity of devices, vendors and
1226
- * their conventions in representing the User-Agent or
1227
- * the HTTP headers.
1228
- *
1229
- * This method will be used to check custom regexes against
1230
- * the User-Agent string.
1231
- *
1232
- * @param $regex
1233
- * @param string $userAgent
1234
- * @return bool
1235
- *
1236
- * @todo: search in the HTTP headers too.
1237
- */
1238
- public function match($regex, $userAgent = null)
1239
- {
1240
- $match = (bool) preg_match(sprintf('#%s#is', $regex), (false === empty($userAgent) ? $userAgent : $this->userAgent), $matches);
1241
- // If positive match is found, store the results for debug.
1242
- if ($match) {
1243
- $this->matchingRegex = $regex;
1244
- $this->matchesArray = $matches;
1245
- }
1246
-
1247
- return $match;
1248
- }
1249
-
1250
- /**
1251
- * Get the properties array.
1252
- *
1253
- * @return array
1254
- */
1255
- public static function getProperties()
1256
- {
1257
- return self::$properties;
1258
- }
1259
-
1260
- /**
1261
- * Prepare the version number.
1262
- *
1263
- * @todo Remove the error supression from str_replace() call.
1264
- *
1265
- * @param string $ver The string version, like "2.6.21.2152";
1266
- *
1267
- * @return float
1268
- */
1269
- public function prepareVersionNo($ver)
1270
- {
1271
- $ver = str_replace(array('_', ' ', '/'), '.', $ver);
1272
- $arrVer = explode('.', $ver, 2);
1273
-
1274
- if (isset($arrVer[1])) {
1275
- $arrVer[1] = @str_replace('.', '', $arrVer[1]); // @todo: treat strings versions.
1276
- }
1277
-
1278
- return (float) implode('.', $arrVer);
1279
- }
1280
-
1281
- /**
1282
- * Check the version of the given property in the User-Agent.
1283
- * Will return a float number. (eg. 2_0 will return 2.0, 4.3.1 will return 4.31)
1284
- *
1285
- * @param string $propertyName The name of the property. See self::getProperties() array
1286
- * keys for all possible properties.
1287
- * @param string $type Either self::VERSION_TYPE_STRING to get a string value or
1288
- * self::VERSION_TYPE_FLOAT indicating a float value. This parameter
1289
- * is optional and defaults to self::VERSION_TYPE_STRING. Passing an
1290
- * invalid parameter will default to the this type as well.
1291
- *
1292
- * @return string|float The version of the property we are trying to extract.
1293
- */
1294
- public function version($propertyName, $type = self::VERSION_TYPE_STRING)
1295
- {
1296
- if (empty($propertyName)) {
1297
- return false;
1298
- }
1299
-
1300
- // set the $type to the default if we don't recognize the type
1301
- if ($type !== self::VERSION_TYPE_STRING && $type !== self::VERSION_TYPE_FLOAT) {
1302
- $type = self::VERSION_TYPE_STRING;
1303
- }
1304
-
1305
- $properties = self::getProperties();
1306
-
1307
- // Check if the property exists in the properties array.
1308
- if (true === isset($properties[$propertyName])) {
1309
-
1310
- // Prepare the pattern to be matched.
1311
- // Make sure we always deal with an array (string is converted).
1312
- $properties[$propertyName] = (array) $properties[$propertyName];
1313
-
1314
- foreach ($properties[$propertyName] as $propertyMatchString) {
1315
-
1316
- $propertyPattern = str_replace('[VER]', self::VER, $propertyMatchString);
1317
-
1318
- // Identify and extract the version.
1319
- preg_match(sprintf('#%s#is', $propertyPattern), $this->userAgent, $match);
1320
-
1321
- if (false === empty($match[1])) {
1322
- $version = ($type == self::VERSION_TYPE_FLOAT ? $this->prepareVersionNo($match[1]) : $match[1]);
1323
-
1324
- return $version;
1325
- }
1326
-
1327
- }
1328
-
1329
- }
1330
-
1331
- return false;
1332
- }
1333
-
1334
- /**
1335
- * Retrieve the mobile grading, using self::MOBILE_GRADE_* constants.
1336
- *
1337
- * @return string One of the self::MOBILE_GRADE_* constants.
1338
- */
1339
- public function mobileGrade()
1340
- {
1341
- $isMobile = $this->isMobile();
1342
-
1343
- if (
1344
- // Apple iOS 4-7.0 – Tested on the original iPad (4.3 / 5.0), iPad 2 (4.3 / 5.1 / 6.1), iPad 3 (5.1 / 6.0), iPad Mini (6.1), iPad Retina (7.0), iPhone 3GS (4.3), iPhone 4 (4.3 / 5.1), iPhone 4S (5.1 / 6.0), iPhone 5 (6.0), and iPhone 5S (7.0)
1345
- $this->is('iOS') && $this->version('iPad', self::VERSION_TYPE_FLOAT) >= 4.3 ||
1346
- $this->is('iOS') && $this->version('iPhone', self::VERSION_TYPE_FLOAT) >= 4.3 ||
1347
- $this->is('iOS') && $this->version('iPod', self::VERSION_TYPE_FLOAT) >= 4.3 ||
1348
-
1349
- // Android 2.1-2.3 - Tested on the HTC Incredible (2.2), original Droid (2.2), HTC Aria (2.1), Google Nexus S (2.3). Functional on 1.5 & 1.6 but performance may be sluggish, tested on Google G1 (1.5)
1350
- // Android 3.1 (Honeycomb) - Tested on the Samsung Galaxy Tab 10.1 and Motorola XOOM
1351
- // Android 4.0 (ICS) - Tested on a Galaxy Nexus. Note: transition performance can be poor on upgraded devices
1352
- // Android 4.1 (Jelly Bean) - Tested on a Galaxy Nexus and Galaxy 7
1353
- ( $this->version('Android', self::VERSION_TYPE_FLOAT)>2.1 && $this->is('Webkit') ) ||
1354
-
1355
- // Windows Phone 7.5-8 - Tested on the HTC Surround (7.5), HTC Trophy (7.5), LG-E900 (7.5), Nokia 800 (7.8), HTC Mazaa (7.8), Nokia Lumia 520 (8), Nokia Lumia 920 (8), HTC 8x (8)
1356
- $this->version('Windows Phone OS', self::VERSION_TYPE_FLOAT) >= 7.5 ||
1357
-
1358
- // Tested on the Torch 9800 (6) and Style 9670 (6), BlackBerry® Torch 9810 (7), BlackBerry Z10 (10)
1359
- $this->is('BlackBerry') && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT) >= 6.0 ||
1360
- // Blackberry Playbook (1.0-2.0) - Tested on PlayBook
1361
- $this->match('Playbook.*Tablet') ||
1362
-
1363
- // Palm WebOS (1.4-3.0) - Tested on the Palm Pixi (1.4), Pre (1.4), Pre 2 (2.0), HP TouchPad (3.0)
1364
- ( $this->version('webOS', self::VERSION_TYPE_FLOAT) >= 1.4 && $this->match('Palm|Pre|Pixi') ) ||
1365
- // Palm WebOS 3.0 - Tested on HP TouchPad
1366
- $this->match('hp.*TouchPad') ||
1367
-
1368
- // Firefox Mobile 18 - Tested on Android 2.3 and 4.1 devices
1369
- ( $this->is('Firefox') && $this->version('Firefox', self::VERSION_TYPE_FLOAT) >= 18 ) ||
1370
-
1371
- // Chrome for Android - Tested on Android 4.0, 4.1 device
1372
- ( $this->is('Chrome') && $this->is('AndroidOS') && $this->version('Android', self::VERSION_TYPE_FLOAT) >= 4.0 ) ||
1373
-
1374
- // Skyfire 4.1 - Tested on Android 2.3 device
1375
- ( $this->is('Skyfire') && $this->version('Skyfire', self::VERSION_TYPE_FLOAT) >= 4.1 && $this->is('AndroidOS') && $this->version('Android', self::VERSION_TYPE_FLOAT) >= 2.3 ) ||
1376
-
1377
- // Opera Mobile 11.5-12: Tested on Android 2.3
1378
- ( $this->is('Opera') && $this->version('Opera Mobi', self::VERSION_TYPE_FLOAT) >= 11.5 && $this->is('AndroidOS') ) ||
1379
-
1380
- // Meego 1.2 - Tested on Nokia 950 and N9
1381
- $this->is('MeeGoOS') ||
1382
-
1383
- // Tizen (pre-release) - Tested on early hardware
1384
- $this->is('Tizen') ||
1385
-
1386
- // Samsung Bada 2.0 - Tested on a Samsung Wave 3, Dolphin browser
1387
- // @todo: more tests here!
1388
- $this->is('Dolfin') && $this->version('Bada', self::VERSION_TYPE_FLOAT) >= 2.0 ||
1389
-
1390
- // UC Browser - Tested on Android 2.3 device
1391
- ( ($this->is('UC Browser') || $this->is('Dolfin')) && $this->version('Android', self::VERSION_TYPE_FLOAT) >= 2.3 ) ||
1392
-
1393
- // Kindle 3 and Fire - Tested on the built-in WebKit browser for each
1394
- ( $this->match('Kindle Fire') ||
1395
- $this->is('Kindle') && $this->version('Kindle', self::VERSION_TYPE_FLOAT) >= 3.0 ) ||
1396
-
1397
- // Nook Color 1.4.1 - Tested on original Nook Color, not Nook Tablet
1398
- $this->is('AndroidOS') && $this->is('NookTablet') ||
1399
-
1400
- // Chrome Desktop 16-24 - Tested on OS X 10.7 and Windows 7
1401
- $this->version('Chrome', self::VERSION_TYPE_FLOAT) >= 16 && !$isMobile ||
1402
-
1403
- // Safari Desktop 5-6 - Tested on OS X 10.7 and Windows 7
1404
- $this->version('Safari', self::VERSION_TYPE_FLOAT) >= 5.0 && !$isMobile ||
1405
-
1406
- // Firefox Desktop 10-18 - Tested on OS X 10.7 and Windows 7
1407
- $this->version('Firefox', self::VERSION_TYPE_FLOAT) >= 10.0 && !$isMobile ||
1408
-
1409
- // Internet Explorer 7-9 - Tested on Windows XP, Vista and 7
1410
- $this->version('IE', self::VERSION_TYPE_FLOAT) >= 7.0 && !$isMobile ||
1411
-
1412
- // Opera Desktop 10-12 - Tested on OS X 10.7 and Windows 7
1413
- $this->version('Opera', self::VERSION_TYPE_FLOAT) >= 10 && !$isMobile
1414
- ){
1415
- return self::MOBILE_GRADE_A;
1416
- }
1417
-
1418
- if (
1419
- $this->is('iOS') && $this->version('iPad', self::VERSION_TYPE_FLOAT)<4.3 ||
1420
- $this->is('iOS') && $this->version('iPhone', self::VERSION_TYPE_FLOAT)<4.3 ||
1421
- $this->is('iOS') && $this->version('iPod', self::VERSION_TYPE_FLOAT)<4.3 ||
1422
-
1423
- // Blackberry 5.0: Tested on the Storm 2 9550, Bold 9770
1424
- $this->is('Blackberry') && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT) >= 5 && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT)<6 ||
1425
-
1426
- //Opera Mini (5.0-6.5) - Tested on iOS 3.2/4.3 and Android 2.3
1427
- ($this->version('Opera Mini', self::VERSION_TYPE_FLOAT) >= 5.0 && $this->version('Opera Mini', self::VERSION_TYPE_FLOAT) <= 7.0 &&
1428
- ($this->version('Android', self::VERSION_TYPE_FLOAT) >= 2.3 || $this->is('iOS')) ) ||
1429
-
1430
- // Nokia Symbian^3 - Tested on Nokia N8 (Symbian^3), C7 (Symbian^3), also works on N97 (Symbian^1)
1431
- $this->match('NokiaN8|NokiaC7|N97.*Series60|Symbian/3') ||
1432
-
1433
- // @todo: report this (tested on Nokia N71)
1434
- $this->version('Opera Mobi', self::VERSION_TYPE_FLOAT) >= 11 && $this->is('SymbianOS')
1435
- ){
1436
- return self::MOBILE_GRADE_B;
1437
- }
1438
-
1439
- if (
1440
- // Blackberry 4.x - Tested on the Curve 8330
1441
- $this->version('BlackBerry', self::VERSION_TYPE_FLOAT) <= 5.0 ||
1442
- // Windows Mobile - Tested on the HTC Leo (WinMo 5.2)
1443
- $this->match('MSIEMobile|Windows CE.*Mobile') || $this->version('Windows Mobile', self::VERSION_TYPE_FLOAT) <= 5.2 ||
1444
-
1445
- // Tested on original iPhone (3.1), iPhone 3 (3.2)
1446
- $this->is('iOS') && $this->version('iPad', self::VERSION_TYPE_FLOAT) <= 3.2 ||
1447
- $this->is('iOS') && $this->version('iPhone', self::VERSION_TYPE_FLOAT) <= 3.2 ||
1448
- $this->is('iOS') && $this->version('iPod', self::VERSION_TYPE_FLOAT) <= 3.2 ||
1449
-
1450
- // Internet Explorer 7 and older - Tested on Windows XP
1451
- $this->version('IE', self::VERSION_TYPE_FLOAT) <= 7.0 && !$isMobile
1452
- ){
1453
- return self::MOBILE_GRADE_C;
1454
- }
1455
-
1456
- // All older smartphone platforms and featurephones - Any device that doesn't support media queries
1457
- // will receive the basic, C grade experience.
1458
- return self::MOBILE_GRADE_C;
1459
- }
1460
- }
1
+ <?php
2
+ namespace Cloudways\Breeze\Mobile_Detect;
3
+ /**
4
+ * Mobile Detect Library
5
+ * =====================
6
+ *
7
+ * Motto: "Every business should have a mobile detection script to detect mobile readers"
8
+ *
9
+ * Mobile_Detect is a lightweight PHP class for detecting mobile devices (including tablets).
10
+ * It uses the User-Agent string combined with specific HTTP headers to detect the mobile environment.
11
+ *
12
+ * @author Current authors: Serban Ghita <serbanghita@gmail.com>
13
+ * Nick Ilyin <nick.ilyin@gmail.com>
14
+ *
15
+ * Original author: Victor Stanciu <vic.stanciu@gmail.com>
16
+ *
17
+ * @license Code and contributions have 'MIT License'
18
+ * More details: https://github.com/serbanghita/Mobile-Detect/blob/master/LICENSE.txt
19
+ *
20
+ * @link Homepage: http://mobiledetect.net
21
+ * GitHub Repo: https://github.com/serbanghita/Mobile-Detect
22
+ * Google Code: http://code.google.com/p/php-mobile-detect/
23
+ * README: https://github.com/serbanghita/Mobile-Detect/blob/master/README.md
24
+ * HOWTO: https://github.com/serbanghita/Mobile-Detect/wiki/Code-examples
25
+ *
26
+ * @version 2.8.25
27
+ */
28
+
29
+ class Mobile_Detect {
30
+
31
+ /**
32
+ * Mobile detection type.
33
+ *
34
+ * @deprecated since version 2.6.9
35
+ */
36
+ const DETECTION_TYPE_MOBILE = 'mobile';
37
+
38
+ /**
39
+ * Extended detection type.
40
+ *
41
+ * @deprecated since version 2.6.9
42
+ */
43
+ const DETECTION_TYPE_EXTENDED = 'extended';
44
+
45
+ /**
46
+ * A frequently used regular expression to extract version #s.
47
+ *
48
+ * @deprecated since version 2.6.9
49
+ */
50
+ const VER = '([\w._\+]+)';
51
+
52
+ /**
53
+ * Top-level device.
54
+ */
55
+ const MOBILE_GRADE_A = 'A';
56
+
57
+ /**
58
+ * Mid-level device.
59
+ */
60
+ const MOBILE_GRADE_B = 'B';
61
+
62
+ /**
63
+ * Low-level device.
64
+ */
65
+ const MOBILE_GRADE_C = 'C';
66
+
67
+ /**
68
+ * Stores the version number of the current release.
69
+ */
70
+ const VERSION = '2.8.25';
71
+
72
+ /**
73
+ * A type for the version() method indicating a string return value.
74
+ */
75
+ const VERSION_TYPE_STRING = 'text';
76
+
77
+ /**
78
+ * A type for the version() method indicating a float return value.
79
+ */
80
+ const VERSION_TYPE_FLOAT = 'float';
81
+
82
+ /**
83
+ * A cache for resolved matches
84
+ * @var array
85
+ */
86
+ protected $cache = array();
87
+
88
+ /**
89
+ * The User-Agent HTTP header is stored in here.
90
+ * @var string
91
+ */
92
+ protected $userAgent = null;
93
+
94
+ /**
95
+ * HTTP headers in the PHP-flavor. So HTTP_USER_AGENT and SERVER_SOFTWARE.
96
+ * @var array
97
+ */
98
+ protected $httpHeaders = array();
99
+
100
+ /**
101
+ * CloudFront headers. E.g. CloudFront-Is-Desktop-Viewer, CloudFront-Is-Mobile-Viewer & CloudFront-Is-Tablet-Viewer.
102
+ * @var array
103
+ */
104
+ protected $cloudfrontHeaders = array();
105
+
106
+ /**
107
+ * The matching Regex.
108
+ * This is good for debug.
109
+ * @var string
110
+ */
111
+ protected $matchingRegex = null;
112
+
113
+ /**
114
+ * The matches extracted from the regex expression.
115
+ * This is good for debug.
116
+ * @var string
117
+ */
118
+ protected $matchesArray = null;
119
+
120
+ /**
121
+ * The detection type, using self::DETECTION_TYPE_MOBILE or self::DETECTION_TYPE_EXTENDED.
122
+ *
123
+ * @deprecated since version 2.6.9
124
+ *
125
+ * @var string
126
+ */
127
+ protected $detectionType = self::DETECTION_TYPE_MOBILE;
128
+
129
+ /**
130
+ * HTTP headers that trigger the 'isMobile' detection
131
+ * to be true.
132
+ *
133
+ * @var array
134
+ */
135
+ protected static $mobileHeaders = array(
136
+
137
+ 'HTTP_ACCEPT' => array(
138
+ 'matches' => array(
139
+ // Opera Mini; @reference: http://dev.opera.com/articles/view/opera-binary-markup-language/
140
+ 'application/x-obml2d',
141
+ // BlackBerry devices.
142
+ 'application/vnd.rim.html',
143
+ 'text/vnd.wap.wml',
144
+ 'application/vnd.wap.xhtml+xml',
145
+ ),
146
+ ),
147
+ 'HTTP_X_WAP_PROFILE' => null,
148
+ 'HTTP_X_WAP_CLIENTID' => null,
149
+ 'HTTP_WAP_CONNECTION' => null,
150
+ 'HTTP_PROFILE' => null,
151
+ // Reported by Opera on Nokia devices (eg. C3).
152
+ 'HTTP_X_OPERAMINI_PHONE_UA' => null,
153
+ 'HTTP_X_NOKIA_GATEWAY_ID' => null,
154
+ 'HTTP_X_ORANGE_ID' => null,
155
+ 'HTTP_X_VODAFONE_3GPDPCONTEXT' => null,
156
+ 'HTTP_X_HUAWEI_USERID' => null,
157
+ // Reported by Windows Smartphones.
158
+ 'HTTP_UA_OS' => null,
159
+ // Reported by Verizon, Vodafone proxy system.
160
+ 'HTTP_X_MOBILE_GATEWAY' => null,
161
+ // Seen this on HTC Sensation. SensationXE_Beats_Z715e.
162
+ 'HTTP_X_ATT_DEVICEID' => null,
163
+ // Seen this on a HTC.
164
+ 'HTTP_UA_CPU' => array( 'matches' => array( 'ARM' ) ),
165
+ );
166
+
167
+ /**
168
+ * List of mobile devices (phones).
169
+ *
170
+ * @var array
171
+ */
172
+ protected static $phoneDevices = array(
173
+ 'iPhone' => '\biPhone\b|\biPod\b', // |\biTunes
174
+ 'BlackBerry' => 'BlackBerry|\bBB10\b|rim[0-9]+',
175
+ 'HTC' => 'HTC|HTC.*(Sensation|Evo|Vision|Explorer|6800|8100|8900|A7272|S510e|C110e|Legend|Desire|T8282)|APX515CKT|Qtek9090|APA9292KT|HD_mini|Sensation.*Z710e|PG86100|Z715e|Desire.*(A8181|HD)|ADR6200|ADR6400L|ADR6425|001HT|Inspire 4G|Android.*\bEVO\b|T-Mobile G1|Z520m',
176
+ 'Nexus' => 'Nexus One|Nexus S|Galaxy.*Nexus|Android.*Nexus.*Mobile|Nexus 4|Nexus 5|Nexus 6',
177
+ // @todo: Is 'Dell Streak' a tablet or a phone? ;)
178
+ 'Dell' => 'Dell.*Streak|Dell.*Aero|Dell.*Venue|DELL.*Venue Pro|Dell Flash|Dell Smoke|Dell Mini 3iX|XCD28|XCD35|\b001DL\b|\b101DL\b|\bGS01\b',
179
+ 'Motorola' => 'Motorola|DROIDX|DROID BIONIC|\bDroid\b.*Build|Android.*Xoom|HRI39|MOT-|A1260|A1680|A555|A853|A855|A953|A955|A956|Motorola.*ELECTRIFY|Motorola.*i1|i867|i940|MB200|MB300|MB501|MB502|MB508|MB511|MB520|MB525|MB526|MB611|MB612|MB632|MB810|MB855|MB860|MB861|MB865|MB870|ME501|ME502|ME511|ME525|ME600|ME632|ME722|ME811|ME860|ME863|ME865|MT620|MT710|MT716|MT720|MT810|MT870|MT917|Motorola.*TITANIUM|WX435|WX445|XT300|XT301|XT311|XT316|XT317|XT319|XT320|XT390|XT502|XT530|XT531|XT532|XT535|XT603|XT610|XT611|XT615|XT681|XT701|XT702|XT711|XT720|XT800|XT806|XT860|XT862|XT875|XT882|XT883|XT894|XT901|XT907|XT909|XT910|XT912|XT928|XT926|XT915|XT919|XT925|XT1021|\bMoto E\b',
180
+ 'Samsung' => '\bSamsung\b|SM-G9250|GT-19300|SGH-I337|BGT-S5230|GT-B2100|GT-B2700|GT-B2710|GT-B3210|GT-B3310|GT-B3410|GT-B3730|GT-B3740|GT-B5510|GT-B5512|GT-B5722|GT-B6520|GT-B7300|GT-B7320|GT-B7330|GT-B7350|GT-B7510|GT-B7722|GT-B7800|GT-C3010|GT-C3011|GT-C3060|GT-C3200|GT-C3212|GT-C3212I|GT-C3262|GT-C3222|GT-C3300|GT-C3300K|GT-C3303|GT-C3303K|GT-C3310|GT-C3322|GT-C3330|GT-C3350|GT-C3500|GT-C3510|GT-C3530|GT-C3630|GT-C3780|GT-C5010|GT-C5212|GT-C6620|GT-C6625|GT-C6712|GT-E1050|GT-E1070|GT-E1075|GT-E1080|GT-E1081|GT-E1085|GT-E1087|GT-E1100|GT-E1107|GT-E1110|GT-E1120|GT-E1125|GT-E1130|GT-E1160|GT-E1170|GT-E1175|GT-E1180|GT-E1182|GT-E1200|GT-E1210|GT-E1225|GT-E1230|GT-E1390|GT-E2100|GT-E2120|GT-E2121|GT-E2152|GT-E2220|GT-E2222|GT-E2230|GT-E2232|GT-E2250|GT-E2370|GT-E2550|GT-E2652|GT-E3210|GT-E3213|GT-I5500|GT-I5503|GT-I5700|GT-I5800|GT-I5801|GT-I6410|GT-I6420|GT-I7110|GT-I7410|GT-I7500|GT-I8000|GT-I8150|GT-I8160|GT-I8190|GT-I8320|GT-I8330|GT-I8350|GT-I8530|GT-I8700|GT-I8703|GT-I8910|GT-I9000|GT-I9001|GT-I9003|GT-I9010|GT-I9020|GT-I9023|GT-I9070|GT-I9082|GT-I9100|GT-I9103|GT-I9220|GT-I9250|GT-I9300|GT-I9305|GT-I9500|GT-I9505|GT-M3510|GT-M5650|GT-M7500|GT-M7600|GT-M7603|GT-M8800|GT-M8910|GT-N7000|GT-S3110|GT-S3310|GT-S3350|GT-S3353|GT-S3370|GT-S3650|GT-S3653|GT-S3770|GT-S3850|GT-S5210|GT-S5220|GT-S5229|GT-S5230|GT-S5233|GT-S5250|GT-S5253|GT-S5260|GT-S5263|GT-S5270|GT-S5300|GT-S5330|GT-S5350|GT-S5360|GT-S5363|GT-S5369|GT-S5380|GT-S5380D|GT-S5560|GT-S5570|GT-S5600|GT-S5603|GT-S5610|GT-S5620|GT-S5660|GT-S5670|GT-S5690|GT-S5750|GT-S5780|GT-S5830|GT-S5839|GT-S6102|GT-S6500|GT-S7070|GT-S7200|GT-S7220|GT-S7230|GT-S7233|GT-S7250|GT-S7500|GT-S7530|GT-S7550|GT-S7562|GT-S7710|GT-S8000|GT-S8003|GT-S8500|GT-S8530|GT-S8600|SCH-A310|SCH-A530|SCH-A570|SCH-A610|SCH-A630|SCH-A650|SCH-A790|SCH-A795|SCH-A850|SCH-A870|SCH-A890|SCH-A930|SCH-A950|SCH-A970|SCH-A990|SCH-I100|SCH-I110|SCH-I400|SCH-I405|SCH-I500|SCH-I510|SCH-I515|SCH-I600|SCH-I730|SCH-I760|SCH-I770|SCH-I830|SCH-I910|SCH-I920|SCH-I959|SCH-LC11|SCH-N150|SCH-N300|SCH-R100|SCH-R300|SCH-R351|SCH-R400|SCH-R410|SCH-T300|SCH-U310|SCH-U320|SCH-U350|SCH-U360|SCH-U365|SCH-U370|SCH-U380|SCH-U410|SCH-U430|SCH-U450|SCH-U460|SCH-U470|SCH-U490|SCH-U540|SCH-U550|SCH-U620|SCH-U640|SCH-U650|SCH-U660|SCH-U700|SCH-U740|SCH-U750|SCH-U810|SCH-U820|SCH-U900|SCH-U940|SCH-U960|SCS-26UC|SGH-A107|SGH-A117|SGH-A127|SGH-A137|SGH-A157|SGH-A167|SGH-A177|SGH-A187|SGH-A197|SGH-A227|SGH-A237|SGH-A257|SGH-A437|SGH-A517|SGH-A597|SGH-A637|SGH-A657|SGH-A667|SGH-A687|SGH-A697|SGH-A707|SGH-A717|SGH-A727|SGH-A737|SGH-A747|SGH-A767|SGH-A777|SGH-A797|SGH-A817|SGH-A827|SGH-A837|SGH-A847|SGH-A867|SGH-A877|SGH-A887|SGH-A897|SGH-A927|SGH-B100|SGH-B130|SGH-B200|SGH-B220|SGH-C100|SGH-C110|SGH-C120|SGH-C130|SGH-C140|SGH-C160|SGH-C170|SGH-C180|SGH-C200|SGH-C207|SGH-C210|SGH-C225|SGH-C230|SGH-C417|SGH-C450|SGH-D307|SGH-D347|SGH-D357|SGH-D407|SGH-D415|SGH-D780|SGH-D807|SGH-D980|SGH-E105|SGH-E200|SGH-E315|SGH-E316|SGH-E317|SGH-E335|SGH-E590|SGH-E635|SGH-E715|SGH-E890|SGH-F300|SGH-F480|SGH-I200|SGH-I300|SGH-I320|SGH-I550|SGH-I577|SGH-I600|SGH-I607|SGH-I617|SGH-I627|SGH-I637|SGH-I677|SGH-I700|SGH-I717|SGH-I727|SGH-i747M|SGH-I777|SGH-I780|SGH-I827|SGH-I847|SGH-I857|SGH-I896|SGH-I897|SGH-I900|SGH-I907|SGH-I917|SGH-I927|SGH-I937|SGH-I997|SGH-J150|SGH-J200|SGH-L170|SGH-L700|SGH-M110|SGH-M150|SGH-M200|SGH-N105|SGH-N500|SGH-N600|SGH-N620|SGH-N625|SGH-N700|SGH-N710|SGH-P107|SGH-P207|SGH-P300|SGH-P310|SGH-P520|SGH-P735|SGH-P777|SGH-Q105|SGH-R210|SGH-R220|SGH-R225|SGH-S105|SGH-S307|SGH-T109|SGH-T119|SGH-T139|SGH-T209|SGH-T219|SGH-T229|SGH-T239|SGH-T249|SGH-T259|SGH-T309|SGH-T319|SGH-T329|SGH-T339|SGH-T349|SGH-T359|SGH-T369|SGH-T379|SGH-T409|SGH-T429|SGH-T439|SGH-T459|SGH-T469|SGH-T479|SGH-T499|SGH-T509|SGH-T519|SGH-T539|SGH-T559|SGH-T589|SGH-T609|SGH-T619|SGH-T629|SGH-T639|SGH-T659|SGH-T669|SGH-T679|SGH-T709|SGH-T719|SGH-T729|SGH-T739|SGH-T746|SGH-T749|SGH-T759|SGH-T769|SGH-T809|SGH-T819|SGH-T839|SGH-T919|SGH-T929|SGH-T939|SGH-T959|SGH-T989|SGH-U100|SGH-U200|SGH-U800|SGH-V205|SGH-V206|SGH-X100|SGH-X105|SGH-X120|SGH-X140|SGH-X426|SGH-X427|SGH-X475|SGH-X495|SGH-X497|SGH-X507|SGH-X600|SGH-X610|SGH-X620|SGH-X630|SGH-X700|SGH-X820|SGH-X890|SGH-Z130|SGH-Z150|SGH-Z170|SGH-ZX10|SGH-ZX20|SHW-M110|SPH-A120|SPH-A400|SPH-A420|SPH-A460|SPH-A500|SPH-A560|SPH-A600|SPH-A620|SPH-A660|SPH-A700|SPH-A740|SPH-A760|SPH-A790|SPH-A800|SPH-A820|SPH-A840|SPH-A880|SPH-A900|SPH-A940|SPH-A960|SPH-D600|SPH-D700|SPH-D710|SPH-D720|SPH-I300|SPH-I325|SPH-I330|SPH-I350|SPH-I500|SPH-I600|SPH-I700|SPH-L700|SPH-M100|SPH-M220|SPH-M240|SPH-M300|SPH-M305|SPH-M320|SPH-M330|SPH-M350|SPH-M360|SPH-M370|SPH-M380|SPH-M510|SPH-M540|SPH-M550|SPH-M560|SPH-M570|SPH-M580|SPH-M610|SPH-M620|SPH-M630|SPH-M800|SPH-M810|SPH-M850|SPH-M900|SPH-M910|SPH-M920|SPH-M930|SPH-N100|SPH-N200|SPH-N240|SPH-N300|SPH-N400|SPH-Z400|SWC-E100|SCH-i909|GT-N7100|GT-N7105|SCH-I535|SM-N900A|SGH-I317|SGH-T999L|GT-S5360B|GT-I8262|GT-S6802|GT-S6312|GT-S6310|GT-S5312|GT-S5310|GT-I9105|GT-I8510|GT-S6790N|SM-G7105|SM-N9005|GT-S5301|GT-I9295|GT-I9195|SM-C101|GT-S7392|GT-S7560|GT-B7610|GT-I5510|GT-S7582|GT-S7530E|GT-I8750|SM-G9006V|SM-G9008V|SM-G9009D|SM-G900A|SM-G900D|SM-G900F|SM-G900H|SM-G900I|SM-G900J|SM-G900K|SM-G900L|SM-G900M|SM-G900P|SM-G900R4|SM-G900S|SM-G900T|SM-G900V|SM-G900W8|SHV-E160K|SCH-P709|SCH-P729|SM-T2558|GT-I9205|SM-G9350|SM-J120F|SM-G920F|SM-G920V|SM-G930F|SM-N910C',
181
+ 'LG' => '\bLG\b;|LG[- ]?(C800|C900|E400|E610|E900|E-900|F160|F180K|F180L|F180S|730|855|L160|LS740|LS840|LS970|LU6200|MS690|MS695|MS770|MS840|MS870|MS910|P500|P700|P705|VM696|AS680|AS695|AX840|C729|E970|GS505|272|C395|E739BK|E960|L55C|L75C|LS696|LS860|P769BK|P350|P500|P509|P870|UN272|US730|VS840|VS950|LN272|LN510|LS670|LS855|LW690|MN270|MN510|P509|P769|P930|UN200|UN270|UN510|UN610|US670|US740|US760|UX265|UX840|VN271|VN530|VS660|VS700|VS740|VS750|VS910|VS920|VS930|VX9200|VX11000|AX840A|LW770|P506|P925|P999|E612|D955|D802|MS323)',
182
+ 'Sony' => 'SonyST|SonyLT|SonyEricsson|SonyEricssonLT15iv|LT18i|E10i|LT28h|LT26w|SonyEricssonMT27i|C5303|C6902|C6903|C6906|C6943|D2533',
183
+ 'Asus' => 'Asus.*Galaxy|PadFone.*Mobile',
184
+ 'NokiaLumia' => 'Lumia [0-9]{3,4}',
185
+ // http://www.micromaxinfo.com/mobiles/smartphones
186
+ // Added because the codes might conflict with Acer Tablets.
187
+ 'Micromax' => 'Micromax.*\b(A210|A92|A88|A72|A111|A110Q|A115|A116|A110|A90S|A26|A51|A35|A54|A25|A27|A89|A68|A65|A57|A90)\b',
188
+ // @todo Complete the regex.
189
+ 'Palm' => 'PalmSource|Palm', // avantgo|blazer|elaine|hiptop|plucker|xiino ;
190
+ 'Vertu' => 'Vertu|Vertu.*Ltd|Vertu.*Ascent|Vertu.*Ayxta|Vertu.*Constellation(F|Quest)?|Vertu.*Monika|Vertu.*Signature', // Just for fun ;)
191
+ // http://www.pantech.co.kr/en/prod/prodList.do?gbrand=VEGA (PANTECH)
192
+ // Most of the VEGA devices are legacy. PANTECH seem to be newer devices based on Android.
193
+ 'Pantech' => 'PANTECH|IM-A850S|IM-A840S|IM-A830L|IM-A830K|IM-A830S|IM-A820L|IM-A810K|IM-A810S|IM-A800S|IM-T100K|IM-A725L|IM-A780L|IM-A775C|IM-A770K|IM-A760S|IM-A750K|IM-A740S|IM-A730S|IM-A720L|IM-A710K|IM-A690L|IM-A690S|IM-A650S|IM-A630K|IM-A600S|VEGA PTL21|PT003|P8010|ADR910L|P6030|P6020|P9070|P4100|P9060|P5000|CDM8992|TXT8045|ADR8995|IS11PT|P2030|P6010|P8000|PT002|IS06|CDM8999|P9050|PT001|TXT8040|P2020|P9020|P2000|P7040|P7000|C790',
194
+ // http://www.fly-phone.com/devices/smartphones/ ; Included only smartphones.
195
+ 'Fly' => 'IQ230|IQ444|IQ450|IQ440|IQ442|IQ441|IQ245|IQ256|IQ236|IQ255|IQ235|IQ245|IQ275|IQ240|IQ285|IQ280|IQ270|IQ260|IQ250',
196
+ // http://fr.wikomobile.com
197
+ 'Wiko' => 'KITE 4G|HIGHWAY|GETAWAY|STAIRWAY|DARKSIDE|DARKFULL|DARKNIGHT|DARKMOON|SLIDE|WAX 4G|RAINBOW|BLOOM|SUNSET|GOA(?!nna)|LENNY|BARRY|IGGY|OZZY|CINK FIVE|CINK PEAX|CINK PEAX 2|CINK SLIM|CINK SLIM 2|CINK +|CINK KING|CINK PEAX|CINK SLIM|SUBLIM',
198
+ 'iMobile' => 'i-mobile (IQ|i-STYLE|idea|ZAA|Hitz)',
199
+ // Added simvalley mobile just for fun. They have some interesting devices.
200
+ // http://www.simvalley.fr/telephonie---gps-_22_telephonie-mobile_telephones_.html
201
+ 'SimValley' => '\b(SP-80|XT-930|SX-340|XT-930|SX-310|SP-360|SP60|SPT-800|SP-120|SPT-800|SP-140|SPX-5|SPX-8|SP-100|SPX-8|SPX-12)\b',
202
+ // Wolfgang - a brand that is sold by Aldi supermarkets.
203
+ // http://www.wolfgangmobile.com/
204
+ 'Wolfgang' => 'AT-B24D|AT-AS50HD|AT-AS40W|AT-AS55HD|AT-AS45q2|AT-B26D|AT-AS50Q',
205
+ 'Alcatel' => 'Alcatel',
206
+ 'Nintendo' => 'Nintendo 3DS',
207
+ // http://en.wikipedia.org/wiki/Amoi
208
+ 'Amoi' => 'Amoi',
209
+ // http://en.wikipedia.org/wiki/INQ
210
+ 'INQ' => 'INQ',
211
+ // @Tapatalk is a mobile app; http://support.tapatalk.com/threads/smf-2-0-2-os-and-browser-detection-plugin-and-tapatalk.15565/#post-79039
212
+ 'GenericPhone' => 'Tapatalk|PDA;|SAGEM|\bmmp\b|pocket|\bpsp\b|symbian|Smartphone|smartfon|treo|up.browser|up.link|vodafone|\bwap\b|nokia|Series40|Series60|S60|SonyEricsson|N900|MAUI.*WAP.*Browser',
213
+ );
214
+
215
+ /**
216
+ * List of tablet devices.
217
+ *
218
+ * @var array
219
+ */
220
+ protected static $tabletDevices = array(
221
+ // @todo: check for mobile friendly emails topic.
222
+ 'iPad' => 'iPad|iPad.*Mobile',
223
+ // Removed |^.*Android.*Nexus(?!(?:Mobile).)*$
224
+ // @see #442
225
+ 'NexusTablet' => 'Android.*Nexus[\s]+(7|9|10)',
226
+ 'SamsungTablet' => 'SAMSUNG.*Tablet|Galaxy.*Tab|SC-01C|GT-P1000|GT-P1003|GT-P1010|GT-P3105|GT-P6210|GT-P6800|GT-P6810|GT-P7100|GT-P7300|GT-P7310|GT-P7500|GT-P7510|SCH-I800|SCH-I815|SCH-I905|SGH-I957|SGH-I987|SGH-T849|SGH-T859|SGH-T869|SPH-P100|GT-P3100|GT-P3108|GT-P3110|GT-P5100|GT-P5110|GT-P6200|GT-P7320|GT-P7511|GT-N8000|GT-P8510|SGH-I497|SPH-P500|SGH-T779|SCH-I705|SCH-I915|GT-N8013|GT-P3113|GT-P5113|GT-P8110|GT-N8010|GT-N8005|GT-N8020|GT-P1013|GT-P6201|GT-P7501|GT-N5100|GT-N5105|GT-N5110|SHV-E140K|SHV-E140L|SHV-E140S|SHV-E150S|SHV-E230K|SHV-E230L|SHV-E230S|SHW-M180K|SHW-M180L|SHW-M180S|SHW-M180W|SHW-M300W|SHW-M305W|SHW-M380K|SHW-M380S|SHW-M380W|SHW-M430W|SHW-M480K|SHW-M480S|SHW-M480W|SHW-M485W|SHW-M486W|SHW-M500W|GT-I9228|SCH-P739|SCH-I925|GT-I9200|GT-P5200|GT-P5210|GT-P5210X|SM-T311|SM-T310|SM-T310X|SM-T210|SM-T210R|SM-T211|SM-P600|SM-P601|SM-P605|SM-P900|SM-P901|SM-T217|SM-T217A|SM-T217S|SM-P6000|SM-T3100|SGH-I467|XE500|SM-T110|GT-P5220|GT-I9200X|GT-N5110X|GT-N5120|SM-P905|SM-T111|SM-T2105|SM-T315|SM-T320|SM-T320X|SM-T321|SM-T520|SM-T525|SM-T530NU|SM-T230NU|SM-T330NU|SM-T900|XE500T1C|SM-P605V|SM-P905V|SM-T337V|SM-T537V|SM-T707V|SM-T807V|SM-P600X|SM-P900X|SM-T210X|SM-T230|SM-T230X|SM-T325|GT-P7503|SM-T531|SM-T330|SM-T530|SM-T705|SM-T705C|SM-T535|SM-T331|SM-T800|SM-T700|SM-T537|SM-T807|SM-P907A|SM-T337A|SM-T537A|SM-T707A|SM-T807A|SM-T237|SM-T807P|SM-P607T|SM-T217T|SM-T337T|SM-T807T|SM-T116NQ|SM-P550|SM-T350|SM-T550|SM-T9000|SM-P9000|SM-T705Y|SM-T805|GT-P3113|SM-T710|SM-T810|SM-T815|SM-T360|SM-T533|SM-T113|SM-T335|SM-T715|SM-T560|SM-T670|SM-T677|SM-T377|SM-T567|SM-T357T|SM-T555|SM-T561|SM-T713|SM-T719|SM-T813|SM-T819|SM-T580|SM-T355Y|SM-T280|SM-T817A|SM-T820|SM-W700|SM-P580|SM-T587', // SCH-P709|SCH-P729|SM-T2558|GT-I9205 - Samsung Mega - treat them like a regular phone.
227
+ // http://docs.aws.amazon.com/silk/latest/developerguide/user-agent.html
228
+ 'Kindle' => 'Kindle|Silk.*Accelerated|Android.*\b(KFOT|KFTT|KFJWI|KFJWA|KFOTE|KFSOWI|KFTHWI|KFTHWA|KFAPWI|KFAPWA|WFJWAE|KFSAWA|KFSAWI|KFASWI|KFARWI|KFFOWI|KFGIWI|KFMEWI)\b|Android.*Silk/[0-9.]+ like Chrome/[0-9.]+ (?!Mobile)',
229
+ // Only the Surface tablets with Windows RT are considered mobile.
230
+ // http://msdn.microsoft.com/en-us/library/ie/hh920767(v=vs.85).aspx
231
+ 'SurfaceTablet' => 'Windows NT [0-9.]+; ARM;.*(Tablet|ARMBJS)',
232
+ // http://shopping1.hp.com/is-bin/INTERSHOP.enfinity/WFS/WW-USSMBPublicStore-Site/en_US/-/USD/ViewStandardCatalog-Browse?CatalogCategoryID=JfIQ7EN5lqMAAAEyDcJUDwMT
233
+ 'HPTablet' => 'HP Slate (7|8|10)|HP ElitePad 900|hp-tablet|EliteBook.*Touch|HP 8|Slate 21|HP SlateBook 10',
234
+ // Watch out for PadFone, see #132.
235
+ // http://www.asus.com/de/Tablets_Mobile/Memo_Pad_Products/
236
+ 'AsusTablet' => '^.*PadFone((?!Mobile).)*$|Transformer|TF101|TF101G|TF300T|TF300TG|TF300TL|TF700T|TF700KL|TF701T|TF810C|ME171|ME301T|ME302C|ME371MG|ME370T|ME372MG|ME172V|ME173X|ME400C|Slider SL101|\bK00F\b|\bK00C\b|\bK00E\b|\bK00L\b|TX201LA|ME176C|ME102A|\bM80TA\b|ME372CL|ME560CG|ME372CG|ME302KL| K010 | K011 | K017 | K01E |ME572C|ME103K|ME170C|ME171C|\bME70C\b|ME581C|ME581CL|ME8510C|ME181C|P01Y|PO1MA|P01Z',
237
+ 'BlackBerryTablet' => 'PlayBook|RIM Tablet',
238
+ 'HTCtablet' => 'HTC_Flyer_P512|HTC Flyer|HTC Jetstream|HTC-P715a|HTC EVO View 4G|PG41200|PG09410',
239
+ 'MotorolaTablet' => 'xoom|sholest|MZ615|MZ605|MZ505|MZ601|MZ602|MZ603|MZ604|MZ606|MZ607|MZ608|MZ609|MZ615|MZ616|MZ617',
240
+ 'NookTablet' => 'Android.*Nook|NookColor|nook browser|BNRV200|BNRV200A|BNTV250|BNTV250A|BNTV400|BNTV600|LogicPD Zoom2',
241
+ // http://www.acer.ro/ac/ro/RO/content/drivers
242
+ // http://www.packardbell.co.uk/pb/en/GB/content/download (Packard Bell is part of Acer)
243
+ // http://us.acer.com/ac/en/US/content/group/tablets
244
+ // http://www.acer.de/ac/de/DE/content/models/tablets/
245
+ // Can conflict with Micromax and Motorola phones codes.
246
+ 'AcerTablet' => 'Android.*; \b(A100|A101|A110|A200|A210|A211|A500|A501|A510|A511|A700|A701|W500|W500P|W501|W501P|W510|W511|W700|G100|G100W|B1-A71|B1-710|B1-711|A1-810|A1-811|A1-830)\b|W3-810|\bA3-A10\b|\bA3-A11\b|\bA3-A20\b|\bA3-A30',
247
+ // http://eu.computers.toshiba-europe.com/innovation/family/Tablets/1098744/banner_id/tablet_footerlink/
248
+ // http://us.toshiba.com/tablets/tablet-finder
249
+ // http://www.toshiba.co.jp/regza/tablet/
250
+ 'ToshibaTablet' => 'Android.*(AT100|AT105|AT200|AT205|AT270|AT275|AT300|AT305|AT1S5|AT500|AT570|AT700|AT830)|TOSHIBA.*FOLIO',
251
+ // http://www.nttdocomo.co.jp/english/service/developer/smart_phone/technical_info/spec/index.html
252
+ // http://www.lg.com/us/tablets
253
+ 'LGTablet' => '\bL-06C|LG-V909|LG-V900|LG-V700|LG-V510|LG-V500|LG-V410|LG-V400|LG-VK810\b',
254
+ 'FujitsuTablet' => 'Android.*\b(F-01D|F-02F|F-05E|F-10D|M532|Q572)\b',
255
+ // Prestigio Tablets http://www.prestigio.com/support
256
+ 'PrestigioTablet' => 'PMP3170B|PMP3270B|PMP3470B|PMP7170B|PMP3370B|PMP3570C|PMP5870C|PMP3670B|PMP5570C|PMP5770D|PMP3970B|PMP3870C|PMP5580C|PMP5880D|PMP5780D|PMP5588C|PMP7280C|PMP7280C3G|PMP7280|PMP7880D|PMP5597D|PMP5597|PMP7100D|PER3464|PER3274|PER3574|PER3884|PER5274|PER5474|PMP5097CPRO|PMP5097|PMP7380D|PMP5297C|PMP5297C_QUAD|PMP812E|PMP812E3G|PMP812F|PMP810E|PMP880TD|PMT3017|PMT3037|PMT3047|PMT3057|PMT7008|PMT5887|PMT5001|PMT5002',
257
+ // http://support.lenovo.com/en_GB/downloads/default.page?#
258
+ 'LenovoTablet' => 'Lenovo TAB|Idea(Tab|Pad)( A1|A10| K1|)|ThinkPad([ ]+)?Tablet|YT3-X90L|YT3-X90F|YT3-X90X|Lenovo.*(S2109|S2110|S5000|S6000|K3011|A3000|A3500|A1000|A2107|A2109|A1107|A5500|A7600|B6000|B8000|B8080)(-|)(FL|F|HV|H|)',
259
+ // http://www.dell.com/support/home/us/en/04/Products/tab_mob/tablets
260
+ 'DellTablet' => 'Venue 11|Venue 8|Venue 7|Dell Streak 10|Dell Streak 7',
261
+ // http://www.yarvik.com/en/matrix/tablets/
262
+ 'YarvikTablet' => 'Android.*\b(TAB210|TAB211|TAB224|TAB250|TAB260|TAB264|TAB310|TAB360|TAB364|TAB410|TAB411|TAB420|TAB424|TAB450|TAB460|TAB461|TAB464|TAB465|TAB467|TAB468|TAB07-100|TAB07-101|TAB07-150|TAB07-151|TAB07-152|TAB07-200|TAB07-201-3G|TAB07-210|TAB07-211|TAB07-212|TAB07-214|TAB07-220|TAB07-400|TAB07-485|TAB08-150|TAB08-200|TAB08-201-3G|TAB08-201-30|TAB09-100|TAB09-211|TAB09-410|TAB10-150|TAB10-201|TAB10-211|TAB10-400|TAB10-410|TAB13-201|TAB274EUK|TAB275EUK|TAB374EUK|TAB462EUK|TAB474EUK|TAB9-200)\b',
263
+ 'MedionTablet' => 'Android.*\bOYO\b|LIFE.*(P9212|P9514|P9516|S9512)|LIFETAB',
264
+ 'ArnovaTablet' => '97G4|AN10G2|AN7bG3|AN7fG3|AN8G3|AN8cG3|AN7G3|AN9G3|AN7dG3|AN7dG3ST|AN7dG3ChildPad|AN10bG3|AN10bG3DT|AN9G2',
265
+ // http://www.intenso.de/kategorie_en.php?kategorie=33
266
+ // @todo: http://www.nbhkdz.com/read/b8e64202f92a2df129126bff.html - investigate
267
+ 'IntensoTablet' => 'INM8002KP|INM1010FP|INM805ND|Intenso Tab|TAB1004',
268
+ // IRU.ru Tablets http://www.iru.ru/catalog/soho/planetable/
269
+ 'IRUTablet' => 'M702pro',
270
+ 'MegafonTablet' => 'MegaFon V9|\bZTE V9\b|Android.*\bMT7A\b',
271
+ // http://www.e-boda.ro/tablete-pc.html
272
+ 'EbodaTablet' => 'E-Boda (Supreme|Impresspeed|Izzycomm|Essential)',
273
+ // http://www.allview.ro/produse/droseries/lista-tablete-pc/
274
+ 'AllViewTablet' => 'Allview.*(Viva|Alldro|City|Speed|All TV|Frenzy|Quasar|Shine|TX1|AX1|AX2)',
275
+ // http://wiki.archosfans.com/index.php?title=Main_Page
276
+ // @note Rewrite the regex format after we add more UAs.
277
+ 'ArchosTablet' => '\b(101G9|80G9|A101IT)\b|Qilive 97R|Archos5|\bARCHOS (70|79|80|90|97|101|FAMILYPAD|)(b|c|)(G10| Cobalt| TITANIUM(HD|)| Xenon| Neon|XSK| 2| XS 2| PLATINUM| CARBON|GAMEPAD)\b',
278
+ // http://www.ainol.com/plugin.php?identifier=ainol&module=product
279
+ 'AinolTablet' => 'NOVO7|NOVO8|NOVO10|Novo7Aurora|Novo7Basic|NOVO7PALADIN|novo9-Spark',
280
+ 'NokiaLumiaTablet' => 'Lumia 2520',
281
+ // @todo: inspect http://esupport.sony.com/US/p/select-system.pl?DIRECTOR=DRIVER
282
+ // Readers http://www.atsuhiro-me.net/ebook/sony-reader/sony-reader-web-browser
283
+ // http://www.sony.jp/support/tablet/
284
+ 'SonyTablet' => 'Sony.*Tablet|Xperia Tablet|Sony Tablet S|SO-03E|SGPT12|SGPT13|SGPT114|SGPT121|SGPT122|SGPT123|SGPT111|SGPT112|SGPT113|SGPT131|SGPT132|SGPT133|SGPT211|SGPT212|SGPT213|SGP311|SGP312|SGP321|EBRD1101|EBRD1102|EBRD1201|SGP351|SGP341|SGP511|SGP512|SGP521|SGP541|SGP551|SGP621|SGP612|SOT31',
285
+ // http://www.support.philips.com/support/catalog/worldproducts.jsp?userLanguage=en&userCountry=cn&categoryid=3G_LTE_TABLET_SU_CN_CARE&title=3G%20tablets%20/%20LTE%20range&_dyncharset=UTF-8
286
+ 'PhilipsTablet' => '\b(PI2010|PI3000|PI3100|PI3105|PI3110|PI3205|PI3210|PI3900|PI4010|PI7000|PI7100)\b',
287
+ // db + http://www.cube-tablet.com/buy-products.html
288
+ 'CubeTablet' => 'Android.*(K8GT|U9GT|U10GT|U16GT|U17GT|U18GT|U19GT|U20GT|U23GT|U30GT)|CUBE U8GT',
289
+ // http://www.cobyusa.com/?p=pcat&pcat_id=3001
290
+ 'CobyTablet' => 'MID1042|MID1045|MID1125|MID1126|MID7012|MID7014|MID7015|MID7034|MID7035|MID7036|MID7042|MID7048|MID7127|MID8042|MID8048|MID8127|MID9042|MID9740|MID9742|MID7022|MID7010',
291
+ // http://www.match.net.cn/products.asp
292
+ 'MIDTablet' => 'M9701|M9000|M9100|M806|M1052|M806|T703|MID701|MID713|MID710|MID727|MID760|MID830|MID728|MID933|MID125|MID810|MID732|MID120|MID930|MID800|MID731|MID900|MID100|MID820|MID735|MID980|MID130|MID833|MID737|MID960|MID135|MID860|MID736|MID140|MID930|MID835|MID733|MID4X10',
293
+ // http://www.msi.com/support
294
+ // @todo Research the Windows Tablets.
295
+ 'MSITablet' => 'MSI \b(Primo 73K|Primo 73L|Primo 81L|Primo 77|Primo 93|Primo 75|Primo 76|Primo 73|Primo 81|Primo 91|Primo 90|Enjoy 71|Enjoy 7|Enjoy 10)\b',
296
+ // @todo http://www.kyoceramobile.com/support/drivers/
297
+ // 'KyoceraTablet' => null,
298
+ // @todo http://intexuae.com/index.php/category/mobile-devices/tablets-products/
299
+ // 'IntextTablet' => null,
300
+ // http://pdadb.net/index.php?m=pdalist&list=SMiT (NoName Chinese Tablets)
301
+ // http://www.imp3.net/14/show.php?itemid=20454
302
+ 'SMiTTablet' => 'Android.*(\bMID\b|MID-560|MTV-T1200|MTV-PND531|MTV-P1101|MTV-PND530)',
303
+ // http://www.rock-chips.com/index.php?do=prod&pid=2
304
+ 'RockChipTablet' => 'Android.*(RK2818|RK2808A|RK2918|RK3066)|RK2738|RK2808A',
305
+ // http://www.fly-phone.com/devices/tablets/ ; http://www.fly-phone.com/service/
306
+ 'FlyTablet' => 'IQ310|Fly Vision',
307
+ // http://www.bqreaders.com/gb/tablets-prices-sale.html
308
+ 'bqTablet' => 'Android.*(bq)?.*(Elcano|Curie|Edison|Maxwell|Kepler|Pascal|Tesla|Hypatia|Platon|Newton|Livingstone|Cervantes|Avant|Aquaris [E|M]10)|Maxwell.*Lite|Maxwell.*Plus',
309
+ // http://www.huaweidevice.com/worldwide/productFamily.do?method=index&directoryId=5011&treeId=3290
310
+ // http://www.huaweidevice.com/worldwide/downloadCenter.do?method=index&directoryId=3372&treeId=0&tb=1&type=software (including legacy tablets)
311
+ 'HuaweiTablet' => 'MediaPad|MediaPad 7 Youth|IDEOS S7|S7-201c|S7-202u|S7-101|S7-103|S7-104|S7-105|S7-106|S7-201|S7-Slim',
312
+ // Nec or Medias Tab
313
+ 'NecTablet' => '\bN-06D|\bN-08D',
314
+ // Pantech Tablets: http://www.pantechusa.com/phones/
315
+ 'PantechTablet' => 'Pantech.*P4100',
316
+ // Broncho Tablets: http://www.broncho.cn/ (hard to find)
317
+ 'BronchoTablet' => 'Broncho.*(N701|N708|N802|a710)',
318
+ // http://versusuk.com/support.html
319
+ 'VersusTablet' => 'TOUCHPAD.*[78910]|\bTOUCHTAB\b',
320
+ // http://www.zync.in/index.php/our-products/tablet-phablets
321
+ 'ZyncTablet' => 'z1000|Z99 2G|z99|z930|z999|z990|z909|Z919|z900',
322
+ // http://www.positivoinformatica.com.br/www/pessoal/tablet-ypy/
323
+ 'PositivoTablet' => 'TB07STA|TB10STA|TB07FTA|TB10FTA',
324
+ // https://www.nabitablet.com/
325
+ 'NabiTablet' => 'Android.*\bNabi',
326
+ 'KoboTablet' => 'Kobo Touch|\bK080\b|\bVox\b Build|\bArc\b Build',
327
+ // French Danew Tablets http://www.danew.com/produits-tablette.php
328
+ 'DanewTablet' => 'DSlide.*\b(700|701R|702|703R|704|802|970|971|972|973|974|1010|1012)\b',
329
+ // Texet Tablets and Readers http://www.texet.ru/tablet/
330
+ 'TexetTablet' => 'NaviPad|TB-772A|TM-7045|TM-7055|TM-9750|TM-7016|TM-7024|TM-7026|TM-7041|TM-7043|TM-7047|TM-8041|TM-9741|TM-9747|TM-9748|TM-9751|TM-7022|TM-7021|TM-7020|TM-7011|TM-7010|TM-7023|TM-7025|TM-7037W|TM-7038W|TM-7027W|TM-9720|TM-9725|TM-9737W|TM-1020|TM-9738W|TM-9740|TM-9743W|TB-807A|TB-771A|TB-727A|TB-725A|TB-719A|TB-823A|TB-805A|TB-723A|TB-715A|TB-707A|TB-705A|TB-709A|TB-711A|TB-890HD|TB-880HD|TB-790HD|TB-780HD|TB-770HD|TB-721HD|TB-710HD|TB-434HD|TB-860HD|TB-840HD|TB-760HD|TB-750HD|TB-740HD|TB-730HD|TB-722HD|TB-720HD|TB-700HD|TB-500HD|TB-470HD|TB-431HD|TB-430HD|TB-506|TB-504|TB-446|TB-436|TB-416|TB-146SE|TB-126SE',
331
+ // Avoid detecting 'PLAYSTATION 3' as mobile.
332
+ 'PlaystationTablet' => 'Playstation.*(Portable|Vita)',
333
+ // http://www.trekstor.de/surftabs.html
334
+ 'TrekstorTablet' => 'ST10416-1|VT10416-1|ST70408-1|ST702xx-1|ST702xx-2|ST80208|ST97216|ST70104-2|VT10416-2|ST10216-2A|SurfTab',
335
+ // http://www.pyleaudio.com/Products.aspx?%2fproducts%2fPersonal-Electronics%2fTablets
336
+ 'PyleAudioTablet' => '\b(PTBL10CEU|PTBL10C|PTBL72BC|PTBL72BCEU|PTBL7CEU|PTBL7C|PTBL92BC|PTBL92BCEU|PTBL9CEU|PTBL9CUK|PTBL9C)\b',
337
+ // http://www.advandigital.com/index.php?link=content-product&jns=JP001
338
+ // because of the short codenames we have to include whitespaces to reduce the possible conflicts.
339
+ 'AdvanTablet' => 'Android.* \b(E3A|T3X|T5C|T5B|T3E|T3C|T3B|T1J|T1F|T2A|T1H|T1i|E1C|T1-E|T5-A|T4|E1-B|T2Ci|T1-B|T1-D|O1-A|E1-A|T1-A|T3A|T4i)\b ',
340
+ // http://www.danytech.com/category/tablet-pc
341
+ 'DanyTechTablet' => 'Genius Tab G3|Genius Tab S2|Genius Tab Q3|Genius Tab G4|Genius Tab Q4|Genius Tab G-II|Genius TAB GII|Genius TAB GIII|Genius Tab S1',
342
+ // http://www.galapad.net/product.html
343
+ 'GalapadTablet' => 'Android.*\bG1\b',
344
+ // http://www.micromaxinfo.com/tablet/funbook
345
+ 'MicromaxTablet' => 'Funbook|Micromax.*\b(P250|P560|P360|P362|P600|P300|P350|P500|P275)\b',
346
+ // http://www.karbonnmobiles.com/products_tablet.php
347
+ 'KarbonnTablet' => 'Android.*\b(A39|A37|A34|ST8|ST10|ST7|Smart Tab3|Smart Tab2)\b',
348
+ // http://www.myallfine.com/Products.asp
349
+ 'AllFineTablet' => 'Fine7 Genius|Fine7 Shine|Fine7 Air|Fine8 Style|Fine9 More|Fine10 Joy|Fine11 Wide',
350
+ // http://www.proscanvideo.com/products-search.asp?itemClass=TABLET&itemnmbr=
351
+ 'PROSCANTablet' => '\b(PEM63|PLT1023G|PLT1041|PLT1044|PLT1044G|PLT1091|PLT4311|PLT4311PL|PLT4315|PLT7030|PLT7033|PLT7033D|PLT7035|PLT7035D|PLT7044K|PLT7045K|PLT7045KB|PLT7071KG|PLT7072|PLT7223G|PLT7225G|PLT7777G|PLT7810K|PLT7849G|PLT7851G|PLT7852G|PLT8015|PLT8031|PLT8034|PLT8036|PLT8080K|PLT8082|PLT8088|PLT8223G|PLT8234G|PLT8235G|PLT8816K|PLT9011|PLT9045K|PLT9233G|PLT9735|PLT9760G|PLT9770G)\b',
352
+ // http://www.yonesnav.com/products/products.php
353
+ 'YONESTablet' => 'BQ1078|BC1003|BC1077|RK9702|BC9730|BC9001|IT9001|BC7008|BC7010|BC708|BC728|BC7012|BC7030|BC7027|BC7026',
354
+ // http://www.cjshowroom.com/eproducts.aspx?classcode=004001001
355
+ // China manufacturer makes tablets for different small brands (eg. http://www.zeepad.net/index.html)
356
+ 'ChangJiaTablet' => 'TPC7102|TPC7103|TPC7105|TPC7106|TPC7107|TPC7201|TPC7203|TPC7205|TPC7210|TPC7708|TPC7709|TPC7712|TPC7110|TPC8101|TPC8103|TPC8105|TPC8106|TPC8203|TPC8205|TPC8503|TPC9106|TPC9701|TPC97101|TPC97103|TPC97105|TPC97106|TPC97111|TPC97113|TPC97203|TPC97603|TPC97809|TPC97205|TPC10101|TPC10103|TPC10106|TPC10111|TPC10203|TPC10205|TPC10503',
357
+ // http://www.gloryunion.cn/products.asp
358
+ // http://www.allwinnertech.com/en/apply/mobile.html
359
+ // http://www.ptcl.com.pk/pd_content.php?pd_id=284 (EVOTAB)
360
+ // @todo: Softwiner tablets?
361
+ // aka. Cute or Cool tablets. Not sure yet, must research to avoid collisions.
362
+ 'GUTablet' => 'TX-A1301|TX-M9002|Q702|kf026', // A12R|D75A|D77|D79|R83|A95|A106C|R15|A75|A76|D71|D72|R71|R73|R77|D82|R85|D92|A97|D92|R91|A10F|A77F|W71F|A78F|W78F|W81F|A97F|W91F|W97F|R16G|C72|C73E|K72|K73|R96G
363
+ // http://www.pointofview-online.com/showroom.php?shop_mode=product_listing&category_id=118
364
+ 'PointOfViewTablet' => 'TAB-P506|TAB-navi-7-3G-M|TAB-P517|TAB-P-527|TAB-P701|TAB-P703|TAB-P721|TAB-P731N|TAB-P741|TAB-P825|TAB-P905|TAB-P925|TAB-PR945|TAB-PL1015|TAB-P1025|TAB-PI1045|TAB-P1325|TAB-PROTAB[0-9]+|TAB-PROTAB25|TAB-PROTAB26|TAB-PROTAB27|TAB-PROTAB26XL|TAB-PROTAB2-IPS9|TAB-PROTAB30-IPS9|TAB-PROTAB25XXL|TAB-PROTAB26-IPS10|TAB-PROTAB30-IPS10',
365
+ // http://www.overmax.pl/pl/katalog-produktow,p8/tablety,c14/
366
+ // @todo: add more tests.
367
+ 'OvermaxTablet' => 'OV-(SteelCore|NewBase|Basecore|Baseone|Exellen|Quattor|EduTab|Solution|ACTION|BasicTab|TeddyTab|MagicTab|Stream|TB-08|TB-09)',
368
+ // http://hclmetablet.com/India/index.php
369
+ 'HCLTablet' => 'HCL.*Tablet|Connect-3G-2.0|Connect-2G-2.0|ME Tablet U1|ME Tablet U2|ME Tablet G1|ME Tablet X1|ME Tablet Y2|ME Tablet Sync',
370
+ // http://www.edigital.hu/Tablet_es_e-book_olvaso/Tablet-c18385.html
371
+ 'DPSTablet' => 'DPS Dream 9|DPS Dual 7',
372
+ // http://www.visture.com/index.asp
373
+ 'VistureTablet' => 'V97 HD|i75 3G|Visture V4( HD)?|Visture V5( HD)?|Visture V10',
374
+ // http://www.mijncresta.nl/tablet
375
+ 'CrestaTablet' => 'CTP(-)?810|CTP(-)?818|CTP(-)?828|CTP(-)?838|CTP(-)?888|CTP(-)?978|CTP(-)?980|CTP(-)?987|CTP(-)?988|CTP(-)?989',
376
+ // MediaTek - http://www.mediatek.com/_en/01_products/02_proSys.php?cata_sn=1&cata1_sn=1&cata2_sn=309
377
+ 'MediatekTablet' => '\bMT8125|MT8389|MT8135|MT8377\b',
378
+ // Concorde tab
379
+ 'ConcordeTablet' => 'Concorde([ ]+)?Tab|ConCorde ReadMan',
380
+ // GoClever Tablets - http://www.goclever.com/uk/products,c1/tablet,c5/
381
+ 'GoCleverTablet' => 'GOCLEVER TAB|A7GOCLEVER|M1042|M7841|M742|R1042BK|R1041|TAB A975|TAB A7842|TAB A741|TAB A741L|TAB M723G|TAB M721|TAB A1021|TAB I921|TAB R721|TAB I720|TAB T76|TAB R70|TAB R76.2|TAB R106|TAB R83.2|TAB M813G|TAB I721|GCTA722|TAB I70|TAB I71|TAB S73|TAB R73|TAB R74|TAB R93|TAB R75|TAB R76.1|TAB A73|TAB A93|TAB A93.2|TAB T72|TAB R83|TAB R974|TAB R973|TAB A101|TAB A103|TAB A104|TAB A104.2|R105BK|M713G|A972BK|TAB A971|TAB R974.2|TAB R104|TAB R83.3|TAB A1042',
382
+ // Modecom Tablets - http://www.modecom.eu/tablets/portal/
383
+ 'ModecomTablet' => 'FreeTAB 9000|FreeTAB 7.4|FreeTAB 7004|FreeTAB 7800|FreeTAB 2096|FreeTAB 7.5|FreeTAB 1014|FreeTAB 1001 |FreeTAB 8001|FreeTAB 9706|FreeTAB 9702|FreeTAB 7003|FreeTAB 7002|FreeTAB 1002|FreeTAB 7801|FreeTAB 1331|FreeTAB 1004|FreeTAB 8002|FreeTAB 8014|FreeTAB 9704|FreeTAB 1003',
384
+ // Vonino Tablets - http://www.vonino.eu/tablets
385
+ 'VoninoTablet' => '\b(Argus[ _]?S|Diamond[ _]?79HD|Emerald[ _]?78E|Luna[ _]?70C|Onyx[ _]?S|Onyx[ _]?Z|Orin[ _]?HD|Orin[ _]?S|Otis[ _]?S|SpeedStar[ _]?S|Magnet[ _]?M9|Primus[ _]?94[ _]?3G|Primus[ _]?94HD|Primus[ _]?QS|Android.*\bQ8\b|Sirius[ _]?EVO[ _]?QS|Sirius[ _]?QS|Spirit[ _]?S)\b',
386
+ // ECS Tablets - http://www.ecs.com.tw/ECSWebSite/Product/Product_Tablet_List.aspx?CategoryID=14&MenuID=107&childid=M_107&LanID=0
387
+ 'ECSTablet' => 'V07OT2|TM105A|S10OT1|TR10CS1',
388
+ // Storex Tablets - http://storex.fr/espace_client/support.html
389
+ // @note: no need to add all the tablet codes since they are guided by the first regex.
390
+ 'StorexTablet' => 'eZee[_\']?(Tab|Go)[0-9]+|TabLC7|Looney Tunes Tab',
391
+ // Generic Vodafone tablets.
392
+ 'VodafoneTablet' => 'SmartTab([ ]+)?[0-9]+|SmartTabII10|SmartTabII7|VF-1497',
393
+ // French tablets - Essentiel B http://www.boulanger.fr/tablette_tactile_e-book/tablette_tactile_essentiel_b/cl_68908.htm?multiChoiceToDelete=brand&mc_brand=essentielb
394
+ // Aka: http://www.essentielb.fr/
395
+ 'EssentielBTablet' => 'Smart[ \']?TAB[ ]+?[0-9]+|Family[ \']?TAB2',
396
+ // Ross & Moor - http://ross-moor.ru/
397
+ 'RossMoorTablet' => 'RM-790|RM-997|RMD-878G|RMD-974R|RMT-705A|RMT-701|RME-601|RMT-501|RMT-711',
398
+ // i-mobile http://product.i-mobilephone.com/Mobile_Device
399
+ 'iMobileTablet' => 'i-mobile i-note',
400
+ // http://www.tolino.de/de/vergleichen/
401
+ 'TolinoTablet' => 'tolino tab [0-9.]+|tolino shine',
402
+ // AudioSonic - a Kmart brand
403
+ // http://www.kmart.com.au/webapp/wcs/stores/servlet/Search?langId=-1&storeId=10701&catalogId=10001&categoryId=193001&pageSize=72&currentPage=1&searchCategory=193001%2b4294965664&sortBy=p_MaxPrice%7c1
404
+ 'AudioSonicTablet' => '\bC-22Q|T7-QC|T-17B|T-17P\b',
405
+ // AMPE Tablets - http://www.ampe.com.my/product-category/tablets/
406
+ // @todo: add them gradually to avoid conflicts.
407
+ 'AMPETablet' => 'Android.* A78 ',
408
+ // Skk Mobile - http://skkmobile.com.ph/product_tablets.php
409
+ 'SkkTablet' => 'Android.* (SKYPAD|PHOENIX|CYCLOPS)',
410
+ // Tecno Mobile (only tablet) - http://www.tecno-mobile.com/index.php/product?filterby=smart&list_order=all&page=1
411
+ 'TecnoTablet' => 'TECNO P9',
412
+ // JXD (consoles & tablets) - http://jxd.hk/products.asp?selectclassid=009008&clsid=3
413
+ 'JXDTablet' => 'Android.* \b(F3000|A3300|JXD5000|JXD3000|JXD2000|JXD300B|JXD300|S5800|S7800|S602b|S5110b|S7300|S5300|S602|S603|S5100|S5110|S601|S7100a|P3000F|P3000s|P101|P200s|P1000m|P200m|P9100|P1000s|S6600b|S908|P1000|P300|S18|S6600|S9100)\b',
414
+ // i-Joy tablets - http://www.i-joy.es/en/cat/products/tablets/
415
+ 'iJoyTablet' => 'Tablet (Spirit 7|Essentia|Galatea|Fusion|Onix 7|Landa|Titan|Scooby|Deox|Stella|Themis|Argon|Unique 7|Sygnus|Hexen|Finity 7|Cream|Cream X2|Jade|Neon 7|Neron 7|Kandy|Scape|Saphyr 7|Rebel|Biox|Rebel|Rebel 8GB|Myst|Draco 7|Myst|Tab7-004|Myst|Tadeo Jones|Tablet Boing|Arrow|Draco Dual Cam|Aurix|Mint|Amity|Revolution|Finity 9|Neon 9|T9w|Amity 4GB Dual Cam|Stone 4GB|Stone 8GB|Andromeda|Silken|X2|Andromeda II|Halley|Flame|Saphyr 9,7|Touch 8|Planet|Triton|Unique 10|Hexen 10|Memphis 4GB|Memphis 8GB|Onix 10)',
416
+ // http://www.intracon.eu/tablet
417
+ 'FX2Tablet' => 'FX2 PAD7|FX2 PAD10',
418
+ // http://www.xoro.de/produkte/
419
+ // @note: Might be the same brand with 'Simply tablets'
420
+ 'XoroTablet' => 'KidsPAD 701|PAD[ ]?712|PAD[ ]?714|PAD[ ]?716|PAD[ ]?717|PAD[ ]?718|PAD[ ]?720|PAD[ ]?721|PAD[ ]?722|PAD[ ]?790|PAD[ ]?792|PAD[ ]?900|PAD[ ]?9715D|PAD[ ]?9716DR|PAD[ ]?9718DR|PAD[ ]?9719QR|PAD[ ]?9720QR|TelePAD1030|Telepad1032|TelePAD730|TelePAD731|TelePAD732|TelePAD735Q|TelePAD830|TelePAD9730|TelePAD795|MegaPAD 1331|MegaPAD 1851|MegaPAD 2151',
421
+ // http://www1.viewsonic.com/products/computing/tablets/
422
+ 'ViewsonicTablet' => 'ViewPad 10pi|ViewPad 10e|ViewPad 10s|ViewPad E72|ViewPad7|ViewPad E100|ViewPad 7e|ViewSonic VB733|VB100a',
423
+ // http://www.odys.de/web/internet-tablet_en.html
424
+ 'OdysTablet' => 'LOOX|XENO10|ODYS[ -](Space|EVO|Xpress|NOON)|\bXELIO\b|Xelio10Pro|XELIO7PHONETAB|XELIO10EXTREME|XELIOPT2|NEO_QUAD10',
425
+ // http://www.captiva-power.de/products.html#tablets-en
426
+ 'CaptivaTablet' => 'CAPTIVA PAD',
427
+ // IconBIT - http://www.iconbit.com/products/tablets/
428
+ 'IconbitTablet' => 'NetTAB|NT-3702|NT-3702S|NT-3702S|NT-3603P|NT-3603P|NT-0704S|NT-0704S|NT-3805C|NT-3805C|NT-0806C|NT-0806C|NT-0909T|NT-0909T|NT-0907S|NT-0907S|NT-0902S|NT-0902S',
429
+ // http://www.teclast.com/topic.php?channelID=70&topicID=140&pid=63
430
+ 'TeclastTablet' => 'T98 4G|\bP80\b|\bX90HD\b|X98 Air|X98 Air 3G|\bX89\b|P80 3G|\bX80h\b|P98 Air|\bX89HD\b|P98 3G|\bP90HD\b|P89 3G|X98 3G|\bP70h\b|P79HD 3G|G18d 3G|\bP79HD\b|\bP89s\b|\bA88\b|\bP10HD\b|\bP19HD\b|G18 3G|\bP78HD\b|\bA78\b|\bP75\b|G17s 3G|G17h 3G|\bP85t\b|\bP90\b|\bP11\b|\bP98t\b|\bP98HD\b|\bG18d\b|\bP85s\b|\bP11HD\b|\bP88s\b|\bA80HD\b|\bA80se\b|\bA10h\b|\bP89\b|\bP78s\b|\bG18\b|\bP85\b|\bA70h\b|\bA70\b|\bG17\b|\bP18\b|\bA80s\b|\bA11s\b|\bP88HD\b|\bA80h\b|\bP76s\b|\bP76h\b|\bP98\b|\bA10HD\b|\bP78\b|\bP88\b|\bA11\b|\bA10t\b|\bP76a\b|\bP76t\b|\bP76e\b|\bP85HD\b|\bP85a\b|\bP86\b|\bP75HD\b|\bP76v\b|\bA12\b|\bP75a\b|\bA15\b|\bP76Ti\b|\bP81HD\b|\bA10\b|\bT760VE\b|\bT720HD\b|\bP76\b|\bP73\b|\bP71\b|\bP72\b|\bT720SE\b|\bC520Ti\b|\bT760\b|\bT720VE\b|T720-3GE|T720-WiFi',
431
+ // Onda - http://www.onda-tablet.com/buy-android-onda.html?dir=desc&limit=all&order=price
432
+ 'OndaTablet' => '\b(V975i|Vi30|VX530|V701|Vi60|V701s|Vi50|V801s|V719|Vx610w|VX610W|V819i|Vi10|VX580W|Vi10|V711s|V813|V811|V820w|V820|Vi20|V711|VI30W|V712|V891w|V972|V819w|V820w|Vi60|V820w|V711|V813s|V801|V819|V975s|V801|V819|V819|V818|V811|V712|V975m|V101w|V961w|V812|V818|V971|V971s|V919|V989|V116w|V102w|V973|Vi40)\b[\s]+',
433
+ 'JaytechTablet' => 'TPC-PA762',
434
+ 'BlaupunktTablet' => 'Endeavour 800NG|Endeavour 1010',
435
+ // http://www.digma.ru/support/download/
436
+ // @todo: Ebooks also (if requested)
437
+ 'DigmaTablet' => '\b(iDx10|iDx9|iDx8|iDx7|iDxD7|iDxD8|iDsQ8|iDsQ7|iDsQ8|iDsD10|iDnD7|3TS804H|iDsQ11|iDj7|iDs10)\b',
438
+ // http://www.evolioshop.com/ro/tablete-pc.html
439
+ // http://www.evolio.ro/support/downloads_static.html?cat=2
440
+ // @todo: Research some more
441
+ 'EvolioTablet' => 'ARIA_Mini_wifi|Aria[ _]Mini|Evolio X10|Evolio X7|Evolio X8|\bEvotab\b|\bNeura\b',
442
+ // @todo http://www.lavamobiles.com/tablets-data-cards
443
+ 'LavaTablet' => 'QPAD E704|\bIvoryS\b|E-TAB IVORY|\bE-TAB\b',
444
+ // http://www.breezetablet.com/
445
+ 'AocTablet' => 'MW0811|MW0812|MW0922|MTK8382|MW1031|MW0831|MW0821|MW0931|MW0712',
446
+ // http://www.mpmaneurope.com/en/products/internet-tablets-14/android-tablets-14/
447
+ 'MpmanTablet' => 'MP11 OCTA|MP10 OCTA|MPQC1114|MPQC1004|MPQC994|MPQC974|MPQC973|MPQC804|MPQC784|MPQC780|\bMPG7\b|MPDCG75|MPDCG71|MPDC1006|MP101DC|MPDC9000|MPDC905|MPDC706HD|MPDC706|MPDC705|MPDC110|MPDC100|MPDC99|MPDC97|MPDC88|MPDC8|MPDC77|MP709|MID701|MID711|MID170|MPDC703|MPQC1010',
448
+ // https://www.celkonmobiles.com/?_a=categoryphones&sid=2
449
+ 'CelkonTablet' => 'CT695|CT888|CT[\s]?910|CT7 Tab|CT9 Tab|CT3 Tab|CT2 Tab|CT1 Tab|C820|C720|\bCT-1\b',
450
+ // http://www.wolderelectronics.com/productos/manuales-y-guias-rapidas/categoria-2-miTab
451
+ 'WolderTablet' => 'miTab \b(DIAMOND|SPACE|BROOKLYN|NEO|FLY|MANHATTAN|FUNK|EVOLUTION|SKY|GOCAR|IRON|GENIUS|POP|MINT|EPSILON|BROADWAY|JUMP|HOP|LEGEND|NEW AGE|LINE|ADVANCE|FEEL|FOLLOW|LIKE|LINK|LIVE|THINK|FREEDOM|CHICAGO|CLEVELAND|BALTIMORE-GH|IOWA|BOSTON|SEATTLE|PHOENIX|DALLAS|IN 101|MasterChef)\b',
452
+ // http://www.mi.com/en
453
+ 'MiTablet' => '\bMI PAD\b|\bHM NOTE 1W\b',
454
+ // http://www.nbru.cn/index.html
455
+ 'NibiruTablet' => 'Nibiru M1|Nibiru Jupiter One',
456
+ // http://navroad.com/products/produkty/tablety/
457
+ 'NexoTablet' => 'NEXO NOVA|NEXO 10|NEXO AVIO|NEXO FREE|NEXO GO|NEXO EVO|NEXO 3G|NEXO SMART|NEXO KIDDO|NEXO MOBI',
458
+ // http://leader-online.com/new_site/product-category/tablets/
459
+ // http://www.leader-online.net.au/List/Tablet
460
+ 'LeaderTablet' => 'TBLT10Q|TBLT10I|TBL-10WDKB|TBL-10WDKBO2013|TBL-W230V2|TBL-W450|TBL-W500|SV572|TBLT7I|TBA-AC7-8G|TBLT79|TBL-8W16|TBL-10W32|TBL-10WKB|TBL-W100',
461
+ // http://www.datawind.com/ubislate/
462
+ 'UbislateTablet' => 'UbiSlate[\s]?7C',
463
+ // http://www.pocketbook-int.com/ru/support
464
+ 'PocketBookTablet' => 'Pocketbook',
465
+ // http://www.kocaso.com/product_tablet.html
466
+ 'KocasoTablet' => '\b(TB-1207)\b',
467
+ // http://global.hisense.com/product/asia/tablet/Sero7/201412/t20141215_91832.htm
468
+ 'HisenseTablet' => '\b(F5281|E2371)\b',
469
+ // http://www.tesco.com/direct/hudl/
470
+ 'Hudl' => 'Hudl HT7S3|Hudl 2',
471
+ // http://www.telstra.com.au/home-phone/thub-2/
472
+ 'TelstraTablet' => 'T-Hub2',
473
+ 'GenericTablet' => 'Android.*\b97D\b|Tablet(?!.*PC)|BNTV250A|MID-WCDMA|LogicPD Zoom2|\bA7EB\b|CatNova8|A1_07|CT704|CT1002|\bM721\b|rk30sdk|\bEVOTAB\b|M758A|ET904|ALUMIUM10|Smartfren Tab|Endeavour 1010|Tablet-PC-4|Tagi Tab|\bM6pro\b|CT1020W|arc 10HD|\bTP750\b',
474
+ );
475
+
476
+ /**
477
+ * List of mobile Operating Systems.
478
+ *
479
+ * @var array
480
+ */
481
+ protected static $operatingSystems = array(
482
+ 'AndroidOS' => 'Android',
483
+ 'BlackBerryOS' => 'blackberry|\bBB10\b|rim tablet os',
484
+ 'PalmOS' => 'PalmOS|avantgo|blazer|elaine|hiptop|palm|plucker|xiino',
485
+ 'SymbianOS' => 'Symbian|SymbOS|Series60|Series40|SYB-[0-9]+|\bS60\b',
486
+ // @reference: http://en.wikipedia.org/wiki/Windows_Mobile
487
+ 'WindowsMobileOS' => 'Windows CE.*(PPC|Smartphone|Mobile|[0-9]{3}x[0-9]{3})|Window Mobile|Windows Phone [0-9.]+|WCE;',
488
+ // @reference: http://en.wikipedia.org/wiki/Windows_Phone
489
+ // http://wifeng.cn/?r=blog&a=view&id=106
490
+ // http://nicksnettravels.builttoroam.com/post/2011/01/10/Bogus-Windows-Phone-7-User-Agent-String.aspx
491
+ // http://msdn.microsoft.com/library/ms537503.aspx
492
+ // https://msdn.microsoft.com/en-us/library/hh869301(v=vs.85).aspx
493
+ 'WindowsPhoneOS' => 'Windows Phone 10.0|Windows Phone 8.1|Windows Phone 8.0|Windows Phone OS|XBLWP7|ZuneWP7|Windows NT 6.[23]; ARM;',
494
+ 'iOS' => '\biPhone.*Mobile|\biPod|\biPad',
495
+ // http://en.wikipedia.org/wiki/MeeGo
496
+ // @todo: research MeeGo in UAs
497
+ 'MeeGoOS' => 'MeeGo',
498
+ // http://en.wikipedia.org/wiki/Maemo
499
+ // @todo: research Maemo in UAs
500
+ 'MaemoOS' => 'Maemo',
501
+ 'JavaOS' => 'J2ME/|\bMIDP\b|\bCLDC\b', // '|Java/' produces bug #135
502
+ 'webOS' => 'webOS|hpwOS',
503
+ 'badaOS' => '\bBada\b',
504
+ 'BREWOS' => 'BREW',
505
+ );
506
+
507
+ /**
508
+ * List of mobile User Agents.
509
+ *
510
+ * IMPORTANT: This is a list of only mobile browsers.
511
+ * Mobile Detect 2.x supports only mobile browsers,
512
+ * it was never designed to detect all browsers.
513
+ * The change will come in 2017 in the 3.x release for PHP7.
514
+ *
515
+ * @var array
516
+ */
517
+ protected static $browsers = array(
518
+ //'Vivaldi' => 'Vivaldi',
519
+ // @reference: https://developers.google.com/chrome/mobile/docs/user-agent
520
+ 'Chrome' => '\bCrMo\b|CriOS|Android.*Chrome/[.0-9]* (Mobile)?',
521
+ 'Dolfin' => '\bDolfin\b',
522
+ 'Opera' => 'Opera.*Mini|Opera.*Mobi|Android.*Opera|Mobile.*OPR/[0-9.]+|Coast/[0-9.]+',
523
+ 'Skyfire' => 'Skyfire',
524
+ 'Edge' => 'Mobile Safari/[.0-9]* Edge',
525
+ 'IE' => 'IEMobile|MSIEMobile', // |Trident/[.0-9]+
526
+ 'Firefox' => 'fennec|firefox.*maemo|(Mobile|Tablet).*Firefox|Firefox.*Mobile|FxiOS',
527
+ 'Bolt' => 'bolt',
528
+ 'TeaShark' => 'teashark',
529
+ 'Blazer' => 'Blazer',
530
+ // @reference: http://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariWebContent/OptimizingforSafarioniPhone/OptimizingforSafarioniPhone.html#//apple_ref/doc/uid/TP40006517-SW3
531
+ 'Safari' => 'Version.*Mobile.*Safari|Safari.*Mobile|MobileSafari',
532
+ // http://en.wikipedia.org/wiki/Midori_(web_browser)
533
+ //'Midori' => 'midori',
534
+ //'Tizen' => 'Tizen',
535
+ 'UCBrowser' => 'UC.*Browser|UCWEB',
536
+ 'baiduboxapp' => 'baiduboxapp',
537
+ 'baidubrowser' => 'baidubrowser',
538
+ // https://github.com/serbanghita/Mobile-Detect/issues/7
539
+ 'DiigoBrowser' => 'DiigoBrowser',
540
+ // http://www.puffinbrowser.com/index.php
541
+ 'Puffin' => 'Puffin',
542
+ // http://mercury-browser.com/index.html
543
+ 'Mercury' => '\bMercury\b',
544
+ // http://en.wikipedia.org/wiki/Obigo_Browser
545
+ 'ObigoBrowser' => 'Obigo',
546
+ // http://en.wikipedia.org/wiki/NetFront
547
+ 'NetFront' => 'NF-Browser',
548
+ // @reference: http://en.wikipedia.org/wiki/Minimo
549
+ // http://en.wikipedia.org/wiki/Vision_Mobile_Browser
550
+ 'GenericBrowser' => 'NokiaBrowser|OviBrowser|OneBrowser|TwonkyBeamBrowser|SEMC.*Browser|FlyFlow|Minimo|NetFront|Novarra-Vision|MQQBrowser|MicroMessenger',
551
+ // @reference: https://en.wikipedia.org/wiki/Pale_Moon_(web_browser)
552
+ 'PaleMoon' => 'Android.*PaleMoon|Mobile.*PaleMoon',
553
+ );
554
+
555
+ /**
556
+ * Utilities.
557
+ *
558
+ * @var array
559
+ */
560
+ protected static $utilities = array(
561
+ // Experimental. When a mobile device wants to switch to 'Desktop Mode'.
562
+ // http://scottcate.com/technology/windows-phone-8-ie10-desktop-or-mobile/
563
+ // https://github.com/serbanghita/Mobile-Detect/issues/57#issuecomment-15024011
564
+ // https://developers.facebook.com/docs/sharing/best-practices
565
+ 'Bot' => 'Googlebot|facebookexternalhit|AdsBot-Google|Google Keyword Suggestion|Facebot|YandexBot|YandexMobileBot|bingbot|ia_archiver|AhrefsBot|Ezooms|GSLFbot|WBSearchBot|Twitterbot|TweetmemeBot|Twikle|PaperLiBot|Wotbox|UnwindFetchor|Exabot|MJ12bot|YandexImages|TurnitinBot|Pingdom',
566
+ 'MobileBot' => 'Googlebot-Mobile|AdsBot-Google-Mobile|YahooSeeker/M1A1-R2D2',
567
+ 'DesktopMode' => 'WPDesktop',
568
+ 'TV' => 'SonyDTV|HbbTV', // experimental
569
+ 'WebKit' => '(webkit)[ /]([\w.]+)',
570
+ // @todo: Include JXD consoles.
571
+ 'Console' => '\b(Nintendo|Nintendo WiiU|Nintendo 3DS|PLAYSTATION|Xbox)\b',
572
+ 'Watch' => 'SM-V700',
573
+ );
574
+
575
+ /**
576
+ * All possible HTTP headers that represent the
577
+ * User-Agent string.
578
+ *
579
+ * @var array
580
+ */
581
+ protected static $uaHttpHeaders = array(
582
+ // The default User-Agent string.
583
+ 'HTTP_USER_AGENT',
584
+ // Header can occur on devices using Opera Mini.
585
+ 'HTTP_X_OPERAMINI_PHONE_UA',
586
+ // Vodafone specific header: http://www.seoprinciple.com/mobile-web-community-still-angry-at-vodafone/24/
587
+ 'HTTP_X_DEVICE_USER_AGENT',
588
+ 'HTTP_X_ORIGINAL_USER_AGENT',
589
+ 'HTTP_X_SKYFIRE_PHONE',
590
+ 'HTTP_X_BOLT_PHONE_UA',
591
+ 'HTTP_DEVICE_STOCK_UA',
592
+ 'HTTP_X_UCBROWSER_DEVICE_UA',
593
+ );
594
+
595
+ /**
596
+ * The individual segments that could exist in a User-Agent string. VER refers to the regular
597
+ * expression defined in the constant self::VER.
598
+ *
599
+ * @var array
600
+ */
601
+ protected static $properties = array(
602
+
603
+ // Build
604
+ 'Mobile' => 'Mobile/[VER]',
605
+ 'Build' => 'Build/[VER]',
606
+ 'Version' => 'Version/[VER]',
607
+ 'VendorID' => 'VendorID/[VER]',
608
+
609
+ // Devices
610
+ 'iPad' => 'iPad.*CPU[a-z ]+[VER]',
611
+ 'iPhone' => 'iPhone.*CPU[a-z ]+[VER]',
612
+ 'iPod' => 'iPod.*CPU[a-z ]+[VER]',
613
+ //'BlackBerry' => array('BlackBerry[VER]', 'BlackBerry [VER];'),
614
+ 'Kindle' => 'Kindle/[VER]',
615
+
616
+ // Browser
617
+ 'Chrome' => array( 'Chrome/[VER]', 'CriOS/[VER]', 'CrMo/[VER]' ),
618
+ 'Coast' => array( 'Coast/[VER]' ),
619
+ 'Dolfin' => 'Dolfin/[VER]',
620
+ // @reference: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent/Firefox
621
+ 'Firefox' => array( 'Firefox/[VER]', 'FxiOS/[VER]' ),
622
+ 'Fennec' => 'Fennec/[VER]',
623
+ // http://msdn.microsoft.com/en-us/library/ms537503(v=vs.85).aspx
624
+ // https://msdn.microsoft.com/en-us/library/ie/hh869301(v=vs.85).aspx
625
+ 'Edge' => 'Edge/[VER]',
626
+ 'IE' => array( 'IEMobile/[VER];', 'IEMobile [VER]', 'MSIE [VER];', 'Trident/[0-9.]+;.*rv:[VER]' ),
627
+ // http://en.wikipedia.org/wiki/NetFront
628
+ 'NetFront' => 'NetFront/[VER]',
629
+ 'NokiaBrowser' => 'NokiaBrowser/[VER]',
630
+ 'Opera' => array( ' OPR/[VER]', 'Opera Mini/[VER]', 'Version/[VER]' ),
631
+ 'Opera Mini' => 'Opera Mini/[VER]',
632
+ 'Opera Mobi' => 'Version/[VER]',
633
+ 'UC Browser' => 'UC Browser[VER]',
634
+ 'MQQBrowser' => 'MQQBrowser/[VER]',
635
+ 'MicroMessenger' => 'MicroMessenger/[VER]',
636
+ 'baiduboxapp' => 'baiduboxapp/[VER]',
637
+ 'baidubrowser' => 'baidubrowser/[VER]',
638
+ 'SamsungBrowser' => 'SamsungBrowser/[VER]',
639
+ 'Iron' => 'Iron/[VER]',
640
+ // @note: Safari 7534.48.3 is actually Version 5.1.
641
+ // @note: On BlackBerry the Version is overwriten by the OS.
642
+ 'Safari' => array( 'Version/[VER]', 'Safari/[VER]' ),
643
+ 'Skyfire' => 'Skyfire/[VER]',
644
+ 'Tizen' => 'Tizen/[VER]',
645
+ 'Webkit' => 'webkit[ /][VER]',
646
+ 'PaleMoon' => 'PaleMoon/[VER]',
647
+
648
+ // Engine
649
+ 'Gecko' => 'Gecko/[VER]',
650
+ 'Trident' => 'Trident/[VER]',
651
+ 'Presto' => 'Presto/[VER]',
652
+ 'Goanna' => 'Goanna/[VER]',
653
+
654
+ // OS
655
+ 'iOS' => ' \bi?OS\b [VER][ ;]{1}',
656
+ 'Android' => 'Android [VER]',
657
+ 'BlackBerry' => array( 'BlackBerry[\w]+/[VER]', 'BlackBerry.*Version/[VER]', 'Version/[VER]' ),
658
+ 'BREW' => 'BREW [VER]',
659
+ 'Java' => 'Java/[VER]',
660
+ // @reference: http://windowsteamblog.com/windows_phone/b/wpdev/archive/2011/08/29/introducing-the-ie9-on-windows-phone-mango-user-agent-string.aspx
661
+ // @reference: http://en.wikipedia.org/wiki/Windows_NT#Releases
662
+ 'Windows Phone OS' => array( 'Windows Phone OS [VER]', 'Windows Phone [VER]' ),
663
+ 'Windows Phone' => 'Windows Phone [VER]',
664
+ 'Windows CE' => 'Windows CE/[VER]',
665
+ // http://social.msdn.microsoft.com/Forums/en-US/windowsdeveloperpreviewgeneral/thread/6be392da-4d2f-41b4-8354-8dcee20c85cd
666
+ 'Windows NT' => 'Windows NT [VER]',
667
+ 'Symbian' => array( 'SymbianOS/[VER]', 'Symbian/[VER]' ),
668
+ 'webOS' => array( 'webOS/[VER]', 'hpwOS/[VER];' ),
669
+ );
670
+
671
+ /**
672
+ * Construct an instance of this class.
673
+ *
674
+ * @param array $headers Specify the headers as injection. Should be PHP _SERVER flavored.
675
+ * If left empty, will use the global _SERVER['HTTP_*'] vars instead.
676
+ * @param string $userAgent Inject the User-Agent header. If null, will use HTTP_USER_AGENT
677
+ * from the $headers array instead.
678
+ */
679
+ public function __construct(
680
+ array $headers = null,
681
+ $userAgent = null
682
+ ) {
683
+ $this->setHttpHeaders( $headers );
684
+ $this->setUserAgent( $userAgent );
685
+ }
686
+
687
+ /**
688
+ * Get the current script version.
689
+ * This is useful for the demo.php file,
690
+ * so people can check on what version they are testing
691
+ * for mobile devices.
692
+ *
693
+ * @return string The version number in semantic version format.
694
+ */
695
+ public static function getScriptVersion() {
696
+ return self::VERSION;
697
+ }
698
+
699
+ /**
700
+ * Set the HTTP Headers. Must be PHP-flavored. This method will reset existing headers.
701
+ *
702
+ * @param array $httpHeaders The headers to set. If null, then using PHP's _SERVER to extract
703
+ * the headers. The default null is left for backwards compatibility.
704
+ */
705
+ public function setHttpHeaders( $httpHeaders = null ) {
706
+ // use global _SERVER if $httpHeaders aren't defined
707
+ if ( ! is_array( $httpHeaders ) || ! count( $httpHeaders ) ) {
708
+ $httpHeaders = $_SERVER;
709
+ }
710
+
711
+ // clear existing headers
712
+ $this->httpHeaders = array();
713
+
714
+ // Only save HTTP headers. In PHP land, that means only _SERVER vars that
715
+ // start with HTTP_.
716
+ foreach ( $httpHeaders as $key => $value ) {
717
+ if ( substr( $key, 0, 5 ) === 'HTTP_' ) {
718
+ $this->httpHeaders[ $key ] = $value;
719
+ }
720
+ }
721
+
722
+ // In case we're dealing with CloudFront, we need to know.
723
+ $this->setCfHeaders( $httpHeaders );
724
+ }
725
+
726
+ /**
727
+ * Retrieves the HTTP headers.
728
+ *
729
+ * @return array
730
+ */
731
+ public function getHttpHeaders() {
732
+ return $this->httpHeaders;
733
+ }
734
+
735
+ /**
736
+ * Retrieves a particular header. If it doesn't exist, no exception/error is caused.
737
+ * Simply null is returned.
738
+ *
739
+ * @param string $header The name of the header to retrieve. Can be HTTP compliant such as
740
+ * "User-Agent" or "X-Device-User-Agent" or can be php-esque with the
741
+ * all-caps, HTTP_ prefixed, underscore seperated awesomeness.
742
+ *
743
+ * @return string|null The value of the header.
744
+ */
745
+ public function getHttpHeader( $header ) {
746
+ // are we using PHP-flavored headers?
747
+ if ( strpos( $header, '_' ) === false ) {
748
+ $header = str_replace( '-', '_', $header );
749
+ $header = strtoupper( $header );
750
+ }
751
+
752
+ // test the alternate, too
753
+ $altHeader = 'HTTP_' . $header;
754
+
755
+ //Test both the regular and the HTTP_ prefix
756
+ if ( isset( $this->httpHeaders[ $header ] ) ) {
757
+ return $this->httpHeaders[ $header ];
758
+ } elseif ( isset( $this->httpHeaders[ $altHeader ] ) ) {
759
+ return $this->httpHeaders[ $altHeader ];
760
+ }
761
+
762
+ return null;
763
+ }
764
+
765
+ public function getMobileHeaders() {
766
+ return self::$mobileHeaders;
767
+ }
768
+
769
+ /**
770
+ * Get all possible HTTP headers that
771
+ * can contain the User-Agent string.
772
+ *
773
+ * @return array List of HTTP headers.
774
+ */
775
+ public function getUaHttpHeaders() {
776
+ return self::$uaHttpHeaders;
777
+ }
778
+
779
+
780
+ /**
781
+ * Set CloudFront headers
782
+ * http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/header-caching.html#header-caching-web-device
783
+ *
784
+ * @param array $cfHeaders List of HTTP headers
785
+ *
786
+ * @return boolean If there were CloudFront headers to be set
787
+ */
788
+ public function setCfHeaders( $cfHeaders = null ) {
789
+ // use global _SERVER if $cfHeaders aren't defined
790
+ if ( ! is_array( $cfHeaders ) || ! count( $cfHeaders ) ) {
791
+ $cfHeaders = $_SERVER;
792
+ }
793
+
794
+ // clear existing headers
795
+ $this->cloudfrontHeaders = array();
796
+
797
+ // Only save CLOUDFRONT headers. In PHP land, that means only _SERVER vars that
798
+ // start with cloudfront-.
799
+ $response = false;
800
+ foreach ( $cfHeaders as $key => $value ) {
801
+ if ( substr( strtolower( $key ), 0, 16 ) === 'http_cloudfront_' ) {
802
+ $this->cloudfrontHeaders[ strtoupper( $key ) ] = $value;
803
+ $response = true;
804
+ }
805
+ }
806
+
807
+ return $response;
808
+ }
809
+
810
+ /**
811
+ * Retrieves the cloudfront headers.
812
+ *
813
+ * @return array
814
+ */
815
+ public function getCfHeaders() {
816
+ return $this->cloudfrontHeaders;
817
+ }
818
+
819
+ /**
820
+ * Set the User-Agent to be used.
821
+ *
822
+ * @param string $userAgent The user agent string to set.
823
+ *
824
+ * @return string|null
825
+ */
826
+ public function setUserAgent( $userAgent = null ) {
827
+ // Invalidate cache due to #375
828
+ $this->cache = array();
829
+
830
+ if ( false === empty( $userAgent ) ) {
831
+ return $this->userAgent = $userAgent;
832
+ } else {
833
+ $this->userAgent = null;
834
+ foreach ( $this->getUaHttpHeaders() as $altHeader ) {
835
+ if ( false === empty( $this->httpHeaders[ $altHeader ] ) ) { // @todo: should use getHttpHeader(), but it would be slow. (Serban)
836
+ $this->userAgent .= $this->httpHeaders[ $altHeader ] . ' ';
837
+ }
838
+ }
839
+
840
+ if ( ! empty( $this->userAgent ) ) {
841
+ return $this->userAgent = trim( $this->userAgent );
842
+ }
843
+ }
844
+
845
+ if ( count( $this->getCfHeaders() ) > 0 ) {
846
+ return $this->userAgent = 'Amazon CloudFront';
847
+ }
848
+ return $this->userAgent = null;
849
+ }
850
+
851
+ /**
852
+ * Retrieve the User-Agent.
853
+ *
854
+ * @return string|null The user agent if it's set.
855
+ */
856
+ public function getUserAgent() {
857
+ return $this->userAgent;
858
+ }
859
+
860
+ /**
861
+ * Set the detection type. Must be one of self::DETECTION_TYPE_MOBILE or
862
+ * self::DETECTION_TYPE_EXTENDED. Otherwise, nothing is set.
863
+ *
864
+ * @deprecated since version 2.6.9
865
+ *
866
+ * @param string $type The type. Must be a self::DETECTION_TYPE_* constant. The default
867
+ * parameter is null which will default to self::DETECTION_TYPE_MOBILE.
868
+ */
869
+ public function setDetectionType( $type = null ) {
870
+ if ( $type === null ) {
871
+ $type = self::DETECTION_TYPE_MOBILE;
872
+ }
873
+
874
+ if ( $type !== self::DETECTION_TYPE_MOBILE && $type !== self::DETECTION_TYPE_EXTENDED ) {
875
+ return;
876
+ }
877
+
878
+ $this->detectionType = $type;
879
+ }
880
+
881
+ public function getMatchingRegex() {
882
+ return $this->matchingRegex;
883
+ }
884
+
885
+ public function getMatchesArray() {
886
+ return $this->matchesArray;
887
+ }
888
+
889
+ /**
890
+ * Retrieve the list of known phone devices.
891
+ *
892
+ * @return array List of phone devices.
893
+ */
894
+ public static function getPhoneDevices() {
895
+ return self::$phoneDevices;
896
+ }
897
+
898
+ /**
899
+ * Retrieve the list of known tablet devices.
900
+ *
901
+ * @return array List of tablet devices.
902
+ */
903
+ public static function getTabletDevices() {
904
+ return self::$tabletDevices;
905
+ }
906
+
907
+ /**
908
+ * Alias for getBrowsers() method.
909
+ *
910
+ * @return array List of user agents.
911
+ */
912
+ public static function getUserAgents() {
913
+ return self::getBrowsers();
914
+ }
915
+
916
+ /**
917
+ * Retrieve the list of known browsers. Specifically, the user agents.
918
+ *
919
+ * @return array List of browsers / user agents.
920
+ */
921
+ public static function getBrowsers() {
922
+ return self::$browsers;
923
+ }
924
+
925
+ /**
926
+ * Retrieve the list of known utilities.
927
+ *
928
+ * @return array List of utilities.
929
+ */
930
+ public static function getUtilities() {
931
+ return self::$utilities;
932
+ }
933
+
934
+ /**
935
+ * Method gets the mobile detection rules. This method is used for the magic methods $detect->is*().
936
+ *
937
+ * @deprecated since version 2.6.9
938
+ *
939
+ * @return array All the rules (but not extended).
940
+ */
941
+ public static function getMobileDetectionRules() {
942
+ static $rules;
943
+
944
+ if ( ! $rules ) {
945
+ $rules = array_merge(
946
+ self::$phoneDevices,
947
+ self::$tabletDevices,
948
+ self::$operatingSystems,
949
+ self::$browsers
950
+ );
951
+ }
952
+
953
+ return $rules;
954
+
955
+ }
956
+
957
+ /**
958
+ * Method gets the mobile detection rules + utilities.
959
+ * The reason this is separate is because utilities rules
960
+ * don't necessary imply mobile. This method is used inside
961
+ * the new $detect->is('stuff') method.
962
+ *
963
+ * @deprecated since version 2.6.9
964
+ *
965
+ * @return array All the rules + extended.
966
+ */
967
+ public function getMobileDetectionRulesExtended() {
968
+ static $rules;
969
+
970
+ if ( ! $rules ) {
971
+ // Merge all rules together.
972
+ $rules = array_merge(
973
+ self::$phoneDevices,
974
+ self::$tabletDevices,
975
+ self::$operatingSystems,
976
+ self::$browsers,
977
+ self::$utilities
978
+ );
979
+ }
980
+
981
+ return $rules;
982
+ }
983
+
984
+ /**
985
+ * Retrieve the current set of rules.
986
+ *
987
+ * @deprecated since version 2.6.9
988
+ *
989
+ * @return array
990
+ */
991
+ public function getRules() {
992
+ if ( $this->detectionType == self::DETECTION_TYPE_EXTENDED ) {
993
+ return self::getMobileDetectionRulesExtended();
994
+ } else {
995
+ return self::getMobileDetectionRules();
996
+ }
997
+ }
998
+
999
+ /**
1000
+ * Retrieve the list of mobile operating systems.
1001
+ *
1002
+ * @return array The list of mobile operating systems.
1003
+ */
1004
+ public static function getOperatingSystems() {
1005
+ return self::$operatingSystems;
1006
+ }
1007
+
1008
+ /**
1009
+ * Check the HTTP headers for signs of mobile.
1010
+ * This is the fastest mobile check possible; it's used
1011
+ * inside isMobile() method.
1012
+ *
1013
+ * @return bool
1014
+ */
1015
+ public function checkHttpHeadersForMobile() {
1016
+ foreach ( $this->getMobileHeaders() as $mobileHeader => $matchType ) {
1017
+ if ( isset( $this->httpHeaders[ $mobileHeader ] ) ) {
1018
+ if ( is_array( $matchType['matches'] ) ) {
1019
+ foreach ( $matchType['matches'] as $_match ) {
1020
+ if ( strpos( $this->httpHeaders[ $mobileHeader ], $_match ) !== false ) {
1021
+ return true;
1022
+ }
1023
+ }
1024
+
1025
+ return false;
1026
+ } else {
1027
+ return true;
1028
+ }
1029
+ }
1030
+ }
1031
+
1032
+ return false;
1033
+
1034
+ }
1035
+
1036
+ /**
1037
+ * Magic overloading method.
1038
+ *
1039
+ * @method boolean is[...]()
1040
+ * @param string $name
1041
+ * @param array $arguments
1042
+ * @return mixed
1043
+ * @throws BadMethodCallException when the method doesn't exist and doesn't start with 'is'
1044
+ */
1045
+ public function __call( $name, $arguments ) {
1046
+ // make sure the name starts with 'is', otherwise
1047
+ if ( substr( $name, 0, 2 ) !== 'is' ) {
1048
+ throw new BadMethodCallException( "No such method exists: $name" );
1049
+ }
1050
+
1051
+ $this->setDetectionType( self::DETECTION_TYPE_MOBILE );
1052
+
1053
+ $key = substr( $name, 2 );
1054
+
1055
+ return $this->matchUAAgainstKey( $key );
1056
+ }
1057
+
1058
+ /**
1059
+ * Find a detection rule that matches the current User-agent.
1060
+ *
1061
+ * @param null $userAgent deprecated
1062
+ * @return boolean
1063
+ */
1064
+ protected function matchDetectionRulesAgainstUA( $userAgent = null ) {
1065
+ // Begin general search.
1066
+ foreach ( $this->getRules() as $_regex ) {
1067
+ if ( empty( $_regex ) ) {
1068
+ continue;
1069
+ }
1070
+
1071
+ if ( $this->match( $_regex, $userAgent ) ) {
1072
+ return true;
1073
+ }
1074
+ }
1075
+
1076
+ return false;
1077
+ }
1078
+
1079
+ /**
1080
+ * Search for a certain key in the rules array.
1081
+ * If the key is found then try to match the corresponding
1082
+ * regex against the User-Agent.
1083
+ *
1084
+ * @param string $key
1085
+ *
1086
+ * @return boolean
1087
+ */
1088
+ protected function matchUAAgainstKey( $key ) {
1089
+ // Make the keys lowercase so we can match: isIphone(), isiPhone(), isiphone(), etc.
1090
+ $key = strtolower( $key );
1091
+ if ( false === isset( $this->cache[ $key ] ) ) {
1092
+
1093
+ // change the keys to lower case
1094
+ $_rules = array_change_key_case( $this->getRules() );
1095
+
1096
+ if ( false === empty( $_rules[ $key ] ) ) {
1097
+ $this->cache[ $key ] = $this->match( $_rules[ $key ] );
1098
+ }
1099
+
1100
+ if ( false === isset( $this->cache[ $key ] ) ) {
1101
+ $this->cache[ $key ] = false;
1102
+ }
1103
+ }
1104
+
1105
+ return $this->cache[ $key ];
1106
+ }
1107
+
1108
+ /**
1109
+ * Check if the device is mobile.
1110
+ * Returns true if any type of mobile device detected, including special ones
1111
+ * @param null $userAgent deprecated
1112
+ * @param null $httpHeaders deprecated
1113
+ * @return bool
1114
+ */
1115
+ public function isMobile( $userAgent = null, $httpHeaders = null ) {
1116
+ if ( $httpHeaders ) {
1117
+ $this->setHttpHeaders( $httpHeaders );
1118
+ }
1119
+
1120
+ if ( $userAgent ) {
1121
+ $this->setUserAgent( $userAgent );
1122
+ }
1123
+
1124
+ // Check specifically for cloudfront headers if the useragent === 'Amazon CloudFront'
1125
+ if ( $this->getUserAgent() === 'Amazon CloudFront' ) {
1126
+ $cfHeaders = $this->getCfHeaders();
1127
+ if ( array_key_exists( 'HTTP_CLOUDFRONT_IS_MOBILE_VIEWER', $cfHeaders ) && $cfHeaders['HTTP_CLOUDFRONT_IS_MOBILE_VIEWER'] === 'true' ) {
1128
+ return true;
1129
+ }
1130
+ }
1131
+
1132
+ $this->setDetectionType( self::DETECTION_TYPE_MOBILE );
1133
+
1134
+ if ( $this->checkHttpHeadersForMobile() ) {
1135
+ return true;
1136
+ } else {
1137
+ return $this->matchDetectionRulesAgainstUA();
1138
+ }
1139
+
1140
+ }
1141
+
1142
+ /**
1143
+ * Check if the device is a tablet.
1144
+ * Return true if any type of tablet device is detected.
1145
+ *
1146
+ * @param string $userAgent deprecated
1147
+ * @param array $httpHeaders deprecated
1148
+ * @return bool
1149
+ */
1150
+ public function isTablet( $userAgent = null, $httpHeaders = null ) {
1151
+ // Check specifically for cloudfront headers if the useragent === 'Amazon CloudFront'
1152
+ if ( $this->getUserAgent() === 'Amazon CloudFront' ) {
1153
+ $cfHeaders = $this->getCfHeaders();
1154
+ if ( array_key_exists( 'HTTP_CLOUDFRONT_IS_TABLET_VIEWER', $cfHeaders ) && $cfHeaders['HTTP_CLOUDFRONT_IS_TABLET_VIEWER'] === 'true' ) {
1155
+ return true;
1156
+ }
1157
+ }
1158
+
1159
+ $this->setDetectionType( self::DETECTION_TYPE_MOBILE );
1160
+
1161
+ foreach ( self::$tabletDevices as $_regex ) {
1162
+ if ( $this->match( $_regex, $userAgent ) ) {
1163
+ return true;
1164
+ }
1165
+ }
1166
+
1167
+ return false;
1168
+ }
1169
+
1170
+ /**
1171
+ * This method checks for a certain property in the
1172
+ * userAgent.
1173
+ * @todo: The httpHeaders part is not yet used.
1174
+ *
1175
+ * @param string $key
1176
+ * @param string $userAgent deprecated
1177
+ * @param string $httpHeaders deprecated
1178
+ * @return bool|int|null
1179
+ */
1180
+ public function is( $key, $userAgent = null, $httpHeaders = null ) {
1181
+ // Set the UA and HTTP headers only if needed (eg. batch mode).
1182
+ if ( $httpHeaders ) {
1183
+ $this->setHttpHeaders( $httpHeaders );
1184
+ }
1185
+
1186
+ if ( $userAgent ) {
1187
+ $this->setUserAgent( $userAgent );
1188
+ }
1189
+
1190
+ $this->setDetectionType( self::DETECTION_TYPE_EXTENDED );
1191
+
1192
+ return $this->matchUAAgainstKey( $key );
1193
+ }
1194
+
1195
+ /**
1196
+ * Some detection rules are relative (not standard),
1197
+ * because of the diversity of devices, vendors and
1198
+ * their conventions in representing the User-Agent or
1199
+ * the HTTP headers.
1200
+ *
1201
+ * This method will be used to check custom regexes against
1202
+ * the User-Agent string.
1203
+ *
1204
+ * @param $regex
1205
+ * @param string $userAgent
1206
+ * @return bool
1207
+ *
1208
+ * @todo: search in the HTTP headers too.
1209
+ */
1210
+ public function match( $regex, $userAgent = null ) {
1211
+ $match = (bool) preg_match( sprintf( '#%s#is', $regex ), ( false === empty( $userAgent ) ? $userAgent : $this->userAgent ), $matches );
1212
+ // If positive match is found, store the results for debug.
1213
+ if ( $match ) {
1214
+ $this->matchingRegex = $regex;
1215
+ $this->matchesArray = $matches;
1216
+ }
1217
+
1218
+ return $match;
1219
+ }
1220
+
1221
+ /**
1222
+ * Get the properties array.
1223
+ *
1224
+ * @return array
1225
+ */
1226
+ public static function getProperties() {
1227
+ return self::$properties;
1228
+ }
1229
+
1230
+ /**
1231
+ * Prepare the version number.
1232
+ *
1233
+ * @todo Remove the error supression from str_replace() call.
1234
+ *
1235
+ * @param string $ver The string version, like "2.6.21.2152";
1236
+ *
1237
+ * @return float
1238
+ */
1239
+ public function prepareVersionNo( $ver ) {
1240
+ $ver = str_replace( array( '_', ' ', '/' ), '.', $ver );
1241
+ $arrVer = explode( '.', $ver, 2 );
1242
+
1243
+ if ( isset( $arrVer[1] ) ) {
1244
+ $arrVer[1] = @str_replace( '.', '', $arrVer[1] ); // @todo: treat strings versions.
1245
+ }
1246
+
1247
+ return (float) implode( '.', $arrVer );
1248
+ }
1249
+
1250
+ /**
1251
+ * Check the version of the given property in the User-Agent.
1252
+ * Will return a float number. (eg. 2_0 will return 2.0, 4.3.1 will return 4.31)
1253
+ *
1254
+ * @param string $propertyName The name of the property. See self::getProperties() array
1255
+ * keys for all possible properties.
1256
+ * @param string $type Either self::VERSION_TYPE_STRING to get a string value or
1257
+ * self::VERSION_TYPE_FLOAT indicating a float value. This parameter
1258
+ * is optional and defaults to self::VERSION_TYPE_STRING. Passing an
1259
+ * invalid parameter will default to the this type as well.
1260
+ *
1261
+ * @return string|float The version of the property we are trying to extract.
1262
+ */
1263
+ public function version( $propertyName, $type = self::VERSION_TYPE_STRING ) {
1264
+ if ( empty( $propertyName ) ) {
1265
+ return false;
1266
+ }
1267
+
1268
+ // set the $type to the default if we don't recognize the type
1269
+ if ( $type !== self::VERSION_TYPE_STRING && $type !== self::VERSION_TYPE_FLOAT ) {
1270
+ $type = self::VERSION_TYPE_STRING;
1271
+ }
1272
+
1273
+ $properties = self::getProperties();
1274
+
1275
+ // Check if the property exists in the properties array.
1276
+ if ( true === isset( $properties[ $propertyName ] ) ) {
1277
+
1278
+ // Prepare the pattern to be matched.
1279
+ // Make sure we always deal with an array (string is converted).
1280
+ $properties[ $propertyName ] = (array) $properties[ $propertyName ];
1281
+
1282
+ foreach ( $properties[ $propertyName ] as $propertyMatchString ) {
1283
+
1284
+ $propertyPattern = str_replace( '[VER]', self::VER, $propertyMatchString );
1285
+
1286
+ // Identify and extract the version.
1287
+ preg_match( sprintf( '#%s#is', $propertyPattern ), $this->userAgent, $match );
1288
+
1289
+ if ( false === empty( $match[1] ) ) {
1290
+ $version = ( $type == self::VERSION_TYPE_FLOAT ? $this->prepareVersionNo( $match[1] ) : $match[1] );
1291
+
1292
+ return $version;
1293
+ }
1294
+ }
1295
+ }
1296
+
1297
+ return false;
1298
+ }
1299
+
1300
+ /**
1301
+ * Retrieve the mobile grading, using self::MOBILE_GRADE_* constants.
1302
+ *
1303
+ * @return string One of the self::MOBILE_GRADE_* constants.
1304
+ */
1305
+ public function mobileGrade() {
1306
+ $isMobile = $this->isMobile();
1307
+
1308
+ if (
1309
+ // Apple iOS 4-7.0 – Tested on the original iPad (4.3 / 5.0), iPad 2 (4.3 / 5.1 / 6.1), iPad 3 (5.1 / 6.0), iPad Mini (6.1), iPad Retina (7.0), iPhone 3GS (4.3), iPhone 4 (4.3 / 5.1), iPhone 4S (5.1 / 6.0), iPhone 5 (6.0), and iPhone 5S (7.0)
1310
+ $this->is( 'iOS' ) && $this->version( 'iPad', self::VERSION_TYPE_FLOAT ) >= 4.3 ||
1311
+ $this->is( 'iOS' ) && $this->version( 'iPhone', self::VERSION_TYPE_FLOAT ) >= 4.3 ||
1312
+ $this->is( 'iOS' ) && $this->version( 'iPod', self::VERSION_TYPE_FLOAT ) >= 4.3 ||
1313
+
1314
+ // Android 2.1-2.3 - Tested on the HTC Incredible (2.2), original Droid (2.2), HTC Aria (2.1), Google Nexus S (2.3). Functional on 1.5 & 1.6 but performance may be sluggish, tested on Google G1 (1.5)
1315
+ // Android 3.1 (Honeycomb) - Tested on the Samsung Galaxy Tab 10.1 and Motorola XOOM
1316
+ // Android 4.0 (ICS) - Tested on a Galaxy Nexus. Note: transition performance can be poor on upgraded devices
1317
+ // Android 4.1 (Jelly Bean) - Tested on a Galaxy Nexus and Galaxy 7
1318
+ ( $this->version( 'Android', self::VERSION_TYPE_FLOAT ) > 2.1 && $this->is( 'Webkit' ) ) ||
1319
+
1320
+ // Windows Phone 7.5-8 - Tested on the HTC Surround (7.5), HTC Trophy (7.5), LG-E900 (7.5), Nokia 800 (7.8), HTC Mazaa (7.8), Nokia Lumia 520 (8), Nokia Lumia 920 (8), HTC 8x (8)
1321
+ $this->version( 'Windows Phone OS', self::VERSION_TYPE_FLOAT ) >= 7.5 ||
1322
+
1323
+ // Tested on the Torch 9800 (6) and Style 9670 (6), BlackBerry® Torch 9810 (7), BlackBerry Z10 (10)
1324
+ $this->is( 'BlackBerry' ) && $this->version( 'BlackBerry', self::VERSION_TYPE_FLOAT ) >= 6.0 ||
1325
+ // Blackberry Playbook (1.0-2.0) - Tested on PlayBook
1326
+ $this->match( 'Playbook.*Tablet' ) ||
1327
+
1328
+ // Palm WebOS (1.4-3.0) - Tested on the Palm Pixi (1.4), Pre (1.4), Pre 2 (2.0), HP TouchPad (3.0)
1329
+ ( $this->version( 'webOS', self::VERSION_TYPE_FLOAT ) >= 1.4 && $this->match( 'Palm|Pre|Pixi' ) ) ||
1330
+ // Palm WebOS 3.0 - Tested on HP TouchPad
1331
+ $this->match( 'hp.*TouchPad' ) ||
1332
+
1333
+ // Firefox Mobile 18 - Tested on Android 2.3 and 4.1 devices
1334
+ ( $this->is( 'Firefox' ) && $this->version( 'Firefox', self::VERSION_TYPE_FLOAT ) >= 18 ) ||
1335
+
1336
+ // Chrome for Android - Tested on Android 4.0, 4.1 device
1337
+ ( $this->is( 'Chrome' ) && $this->is( 'AndroidOS' ) && $this->version( 'Android', self::VERSION_TYPE_FLOAT ) >= 4.0 ) ||
1338
+
1339
+ // Skyfire 4.1 - Tested on Android 2.3 device
1340
+ ( $this->is( 'Skyfire' ) && $this->version( 'Skyfire', self::VERSION_TYPE_FLOAT ) >= 4.1 && $this->is( 'AndroidOS' ) && $this->version( 'Android', self::VERSION_TYPE_FLOAT ) >= 2.3 ) ||
1341
+
1342
+ // Opera Mobile 11.5-12: Tested on Android 2.3
1343
+ ( $this->is( 'Opera' ) && $this->version( 'Opera Mobi', self::VERSION_TYPE_FLOAT ) >= 11.5 && $this->is( 'AndroidOS' ) ) ||
1344
+
1345
+ // Meego 1.2 - Tested on Nokia 950 and N9
1346
+ $this->is( 'MeeGoOS' ) ||
1347
+
1348
+ // Tizen (pre-release) - Tested on early hardware
1349
+ $this->is( 'Tizen' ) ||
1350
+
1351
+ // Samsung Bada 2.0 - Tested on a Samsung Wave 3, Dolphin browser
1352
+ // @todo: more tests here!
1353
+ $this->is( 'Dolfin' ) && $this->version( 'Bada', self::VERSION_TYPE_FLOAT ) >= 2.0 ||
1354
+
1355
+ // UC Browser - Tested on Android 2.3 device
1356
+ ( ( $this->is( 'UC Browser' ) || $this->is( 'Dolfin' ) ) && $this->version( 'Android', self::VERSION_TYPE_FLOAT ) >= 2.3 ) ||
1357
+
1358
+ // Kindle 3 and Fire - Tested on the built-in WebKit browser for each
1359
+ ( $this->match( 'Kindle Fire' ) ||
1360
+ $this->is( 'Kindle' ) && $this->version( 'Kindle', self::VERSION_TYPE_FLOAT ) >= 3.0 ) ||
1361
+
1362
+ // Nook Color 1.4.1 - Tested on original Nook Color, not Nook Tablet
1363
+ $this->is( 'AndroidOS' ) && $this->is( 'NookTablet' ) ||
1364
+
1365
+ // Chrome Desktop 16-24 - Tested on OS X 10.7 and Windows 7
1366
+ $this->version( 'Chrome', self::VERSION_TYPE_FLOAT ) >= 16 && ! $isMobile ||
1367
+
1368
+ // Safari Desktop 5-6 - Tested on OS X 10.7 and Windows 7
1369
+ $this->version( 'Safari', self::VERSION_TYPE_FLOAT ) >= 5.0 && ! $isMobile ||
1370
+
1371
+ // Firefox Desktop 10-18 - Tested on OS X 10.7 and Windows 7
1372
+ $this->version( 'Firefox', self::VERSION_TYPE_FLOAT ) >= 10.0 && ! $isMobile ||
1373
+
1374
+ // Internet Explorer 7-9 - Tested on Windows XP, Vista and 7
1375
+ $this->version( 'IE', self::VERSION_TYPE_FLOAT ) >= 7.0 && ! $isMobile ||
1376
+
1377
+ // Opera Desktop 10-12 - Tested on OS X 10.7 and Windows 7
1378
+ $this->version( 'Opera', self::VERSION_TYPE_FLOAT ) >= 10 && ! $isMobile
1379
+ ) {
1380
+ return self::MOBILE_GRADE_A;
1381
+ }
1382
+
1383
+ if (
1384
+ $this->is( 'iOS' ) && $this->version( 'iPad', self::VERSION_TYPE_FLOAT ) < 4.3 ||
1385
+ $this->is( 'iOS' ) && $this->version( 'iPhone', self::VERSION_TYPE_FLOAT ) < 4.3 ||
1386
+ $this->is( 'iOS' ) && $this->version( 'iPod', self::VERSION_TYPE_FLOAT ) < 4.3 ||
1387
+
1388
+ // Blackberry 5.0: Tested on the Storm 2 9550, Bold 9770
1389
+ $this->is( 'Blackberry' ) && $this->version( 'BlackBerry', self::VERSION_TYPE_FLOAT ) >= 5 && $this->version( 'BlackBerry', self::VERSION_TYPE_FLOAT ) < 6 ||
1390
+
1391
+ //Opera Mini (5.0-6.5) - Tested on iOS 3.2/4.3 and Android 2.3
1392
+ ( $this->version( 'Opera Mini', self::VERSION_TYPE_FLOAT ) >= 5.0 && $this->version( 'Opera Mini', self::VERSION_TYPE_FLOAT ) <= 7.0 &&
1393
+ ( $this->version( 'Android', self::VERSION_TYPE_FLOAT ) >= 2.3 || $this->is( 'iOS' ) ) ) ||
1394
+
1395
+ // Nokia Symbian^3 - Tested on Nokia N8 (Symbian^3), C7 (Symbian^3), also works on N97 (Symbian^1)
1396
+ $this->match( 'NokiaN8|NokiaC7|N97.*Series60|Symbian/3' ) ||
1397
+
1398
+ // @todo: report this (tested on Nokia N71)
1399
+ $this->version( 'Opera Mobi', self::VERSION_TYPE_FLOAT ) >= 11 && $this->is( 'SymbianOS' )
1400
+ ) {
1401
+ return self::MOBILE_GRADE_B;
1402
+ }
1403
+
1404
+ if (
1405
+ // Blackberry 4.x - Tested on the Curve 8330
1406
+ $this->version( 'BlackBerry', self::VERSION_TYPE_FLOAT ) <= 5.0 ||
1407
+ // Windows Mobile - Tested on the HTC Leo (WinMo 5.2)
1408
+ $this->match( 'MSIEMobile|Windows CE.*Mobile' ) || $this->version( 'Windows Mobile', self::VERSION_TYPE_FLOAT ) <= 5.2 ||
1409
+
1410
+ // Tested on original iPhone (3.1), iPhone 3 (3.2)
1411
+ $this->is( 'iOS' ) && $this->version( 'iPad', self::VERSION_TYPE_FLOAT ) <= 3.2 ||
1412
+ $this->is( 'iOS' ) && $this->version( 'iPhone', self::VERSION_TYPE_FLOAT ) <= 3.2 ||
1413
+ $this->is( 'iOS' ) && $this->version( 'iPod', self::VERSION_TYPE_FLOAT ) <= 3.2 ||
1414
+
1415
+ // Internet Explorer 7 and older - Tested on Windows XP
1416
+ $this->version( 'IE', self::VERSION_TYPE_FLOAT ) <= 7.0 && ! $isMobile
1417
+ ) {
1418
+ return self::MOBILE_GRADE_C;
1419
+ }
1420
+
1421
+ // All older smartphone platforms and featurephones - Any device that doesn't support media queries
1422
+ // will receive the basic, C grade experience.
1423
+ return self::MOBILE_GRADE_C;
1424
+ }
1425
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/cache/Mobile-Detect-2.8.25/export/exportToJSON.php CHANGED
@@ -1,67 +1,66 @@
1
- <?php
2
- /**
3
- * Mobile Detect Library
4
- * - export -
5
- * =====================
6
- *
7
- * Use the resulting JSON export file in other languages
8
- * other than PHP. Always check for 'version' key because
9
- * new major versions can modify the structure of the JSON file.
10
- *
11
- * The result of running this script is the export.json file.
12
- *
13
- * @license Code and contributions have 'MIT License'
14
- * More details: https://github.com/serbanghita/Mobile-Detect/blob/master/LICENSE.txt
15
- *
16
- */
17
-
18
- // Included nicejson function to beautify the result JSON file.
19
- // This library is not mandatory.
20
- if( file_exists(dirname(__FILE__).'/nicejson/nicejson.php') ) {
21
- include_once dirname(__FILE__).'/nicejson/nicejson.php';
22
- }
23
-
24
- // Include Mobile Detect.
25
- require_once dirname(__FILE__).'/../Mobile_Detect.php';
26
- $detect = new Mobile_Detect;
27
-
28
- $json = array(
29
- // The current version of Mobile Detect class that
30
- // is being exported.
31
- 'version' => $detect->getScriptVersion(),
32
-
33
- // All headers that trigger 'isMobile' to be 'true',
34
- // before reaching the User-Agent match detection.
35
- 'headerMatch' => $detect->getMobileHeaders(),
36
-
37
- // All possible User-Agent headers.
38
- 'uaHttpHeaders' => $detect->getUaHttpHeaders(),
39
-
40
- // All the regexes that trigger 'isMobile' or 'isTablet'
41
- // to be true.
42
- 'uaMatch' => array(
43
- // If match is found, triggers 'isMobile' to be true.
44
- 'phones' => $detect->getPhoneDevices(),
45
- // Triggers 'isTablet' to be true.
46
- 'tablets' => $detect->getTabletDevices(),
47
- // If match is found, triggers 'isMobile' to be true.
48
- 'browsers' => $detect->getBrowsers(),
49
- // If match is found, triggers 'isMobile' to be true.
50
- 'os' => $detect->getOperatingSystems(),
51
- // Various utilities. To be further discussed.
52
- 'utilities' => $detect->getUtilities()
53
- )
54
- );
55
-
56
- $fileName = dirname(__FILE__).'/../Mobile_Detect.json';
57
- // Write the JSON file to disk.11
58
- // You can import this file in your app.
59
- if (file_put_contents(
60
- $fileName,
61
- function_exists('json_format') ? json_format($json) : json_encode($json)
62
- )) {
63
- echo 'Done. Check '.realpath($fileName).' file.';
64
- }
65
- else {
66
- echo 'Failed to write '.realpath($fileName).' to disk.';
67
- }
1
+ <?php
2
+ /**
3
+ * Mobile Detect Library
4
+ * - export -
5
+ * =====================
6
+ *
7
+ * Use the resulting JSON export file in other languages
8
+ * other than PHP. Always check for 'version' key because
9
+ * new major versions can modify the structure of the JSON file.
10
+ *
11
+ * The result of running this script is the export.json file.
12
+ *
13
+ * @license Code and contributions have 'MIT License'
14
+ * More details: https://github.com/serbanghita/Mobile-Detect/blob/master/LICENSE.txt
15
+ *
16
+ */
17
+
18
+ // Included nicejson function to beautify the result JSON file.
19
+ // This library is not mandatory.
20
+ if ( file_exists( dirname( __FILE__ ) . '/nicejson/nicejson.php' ) ) {
21
+ include_once dirname( __FILE__ ) . '/nicejson/nicejson.php';
22
+ }
23
+
24
+ // Include Mobile Detect.
25
+ require_once dirname( __FILE__ ) . '/../Mobile_Detect.php';
26
+ $detect = new Mobile_Detect;
27
+
28
+ $json = array(
29
+ // The current version of Mobile Detect class that
30
+ // is being exported.
31
+ 'version' => $detect->getScriptVersion(),
32
+
33
+ // All headers that trigger 'isMobile' to be 'true',
34
+ // before reaching the User-Agent match detection.
35
+ 'headerMatch' => $detect->getMobileHeaders(),
36
+
37
+ // All possible User-Agent headers.
38
+ 'uaHttpHeaders' => $detect->getUaHttpHeaders(),
39
+
40
+ // All the regexes that trigger 'isMobile' or 'isTablet'
41
+ // to be true.
42
+ 'uaMatch' => array(
43
+ // If match is found, triggers 'isMobile' to be true.
44
+ 'phones' => $detect->getPhoneDevices(),
45
+ // Triggers 'isTablet' to be true.
46
+ 'tablets' => $detect->getTabletDevices(),
47
+ // If match is found, triggers 'isMobile' to be true.
48
+ 'browsers' => $detect->getBrowsers(),
49
+ // If match is found, triggers 'isMobile' to be true.
50
+ 'os' => $detect->getOperatingSystems(),
51
+ // Various utilities. To be further discussed.
52
+ 'utilities' => $detect->getUtilities(),
53
+ ),
54
+ );
55
+
56
+ $fileName = dirname( __FILE__ ) . '/../Mobile_Detect.json';
57
+ // Write the JSON file to disk.11
58
+ // You can import this file in your app.
59
+ if ( file_put_contents(
60
+ $fileName,
61
+ function_exists( 'json_format' ) ? json_format( $json ) : json_encode( $json )
62
+ ) ) {
63
+ echo 'Done. Check ' . realpath( $fileName ) . ' file.';
64
+ } else {
65
+ echo 'Failed to write ' . realpath( $fileName ) . ' to disk.';
66
+ }
 
inc/cache/Mobile-Detect-2.8.25/namespaced/Detection/MobileDetect.php CHANGED
@@ -1,22 +1,22 @@
1
- <?php
2
- /**
3
- * Little piece of PHP to make Mobile_Detect auto-loadable in PSR-0 compatible PHP autoloaders like
4
- * the Symfony Universal ClassLoader by Fabien Potencier. Since PSR-0 handles an underscore in
5
- * classnames (on the filesystem) as a slash, "Mobile_Detect.php" autoloaders will try to convert
6
- * the classname and path to "Mobile\Detect.php". This script will ensure autoloading with:
7
- * - Namespace: Detection
8
- * - Classname: MobileDetect
9
- * - Namespased: \Detection\MobileDetect
10
- * - Autoload path: ./namespaced
11
- * - Converted path: ./namespaced/Detection/MobileDetect.php
12
- *
13
- * Don't forget to use MobileDetect (instead of Mobile_Detect) as class in code when autoloading.
14
- *
15
- * Thanks to @WietseWind.
16
- * For details please check: https://github.com/serbanghita/Mobile-Detect/pull/120
17
- */
18
-
19
- namespace Detection;
20
- require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'Mobile_Detect.php';
21
-
22
- class MobileDetect extends \Mobile_Detect {}
1
+ <?php
2
+ /**
3
+ * Little piece of PHP to make Mobile_Detect auto-loadable in PSR-0 compatible PHP autoloaders like
4
+ * the Symfony Universal ClassLoader by Fabien Potencier. Since PSR-0 handles an underscore in
5
+ * classnames (on the filesystem) as a slash, "Mobile_Detect.php" autoloaders will try to convert
6
+ * the classname and path to "Mobile\Detect.php". This script will ensure autoloading with:
7
+ * - Namespace: Detection
8
+ * - Classname: MobileDetect
9
+ * - Namespased: \Detection\MobileDetect
10
+ * - Autoload path: ./namespaced
11
+ * - Converted path: ./namespaced/Detection/MobileDetect.php
12
+ *
13
+ * Don't forget to use MobileDetect (instead of Mobile_Detect) as class in code when autoloading.
14
+ *
15
+ * Thanks to @WietseWind.
16
+ * For details please check: https://github.com/serbanghita/Mobile-Detect/pull/120
17
+ */
18
+
19
+ namespace Detection;
20
+ require_once dirname( __FILE__ ) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'Mobile_Detect.php';
21
+
22
+ class MobileDetect extends \Mobile_Detect {}
inc/cache/config-cache.php CHANGED
@@ -1,347 +1,489 @@
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
- //Based on some work of simple-cache
22
- if ( ! defined( 'ABSPATH' ) ) exit;
23
-
24
- class Breeze_ConfigCache {
25
-
26
- /**
27
- * Create advanced-cache file
28
- */
29
- public function write() {
30
- global $wp_filesystem;
31
-
32
- $file = trailingslashit( WP_CONTENT_DIR ) . '/advanced-cache.php';
33
-
34
- // Create array of configuration files and their corresponding sites' URLs.
35
- $cache_configs = array(
36
- 'breeze-config' => array(),
37
- );
38
- if ( is_multisite() ) {
39
- // This is a multisite install, loop through all subsites.
40
- $blogs = get_sites(
41
- array(
42
- 'fields' => 'ids',
43
- )
44
- );
45
-
46
- foreach ( $blogs as $blog_id ) {
47
- switch_to_blog( $blog_id );
48
- $config = breeze_get_option( 'basic_settings' );
49
- if ( ! empty( $config['breeze-active'] ) ) {
50
- $inherit_option = get_option( 'breeze_inherit_settings' );
51
-
52
- if ( '0' === $inherit_option ) {
53
- // Site uses own (custom) configuration.
54
- $cache_configs[ "breeze-config-{$blog_id}" ] = preg_replace( '(^https?://)', '', site_url() );
55
- } else {
56
- // Site uses global configuration.
57
- $cache_configs['breeze-config'][] = preg_replace( '(^https?://)', '', site_url() );
58
- }
59
- }
60
- restore_current_blog();
61
- }
62
- } else {
63
- $config = breeze_get_option( 'basic_settings' );
64
-
65
- if ( ! empty( $config['breeze-active'] ) ) {
66
- $cache_configs['breeze-config'][] = preg_replace( '(^https?://)', '', site_url() );
67
- }
68
- }
69
-
70
- if ( empty( $cache_configs ) || ( 1 === count( $cache_configs ) && empty( $cache_configs['breeze-config'] ) ) ) {
71
- // No sites with caching enabled.
72
- $this->clean_config();
73
- return;
74
- } else {
75
- $file_string = '<?php ' .
76
- "\n\r" . 'defined( \'ABSPATH\' ) || exit;' .
77
- "\n\r" . 'define( \'BREEZE_ADVANCED_CACHE\', true );' .
78
- "\n\r" . 'if ( is_admin() ) { return; }' .
79
- "\n\r" . 'if ( ! @file_exists( \'' . BREEZE_PLUGIN_DIR . 'breeze.php\' ) ) { return; }';
80
- }
81
-
82
- if ( 1 === count( $cache_configs ) ) {
83
- // Only 1 config file available.
84
- $blog_file = trailingslashit( WP_CONTENT_DIR ) . 'breeze-config/breeze-config.php';
85
- $file_string .= "\n\$config = '$blog_file';";
86
- } else {
87
- // Multiple configuration files, load appropriate one by comparing URLs.
88
- $file_string .= "\n\r" . '$domain = strtolower( stripslashes( $_SERVER[\'HTTP_HOST\'] ) );' .
89
- "\n" . 'if ( substr( $domain, -3 ) == \':80\' ) {' .
90
- "\n" . ' $domain = substr( $domain, 0, -3 );' .
91
- "\n" . '} elseif ( substr( $domain, -4 ) == \':443\' ) {' .
92
- "\n" . ' $domain = substr( $domain, 0, -4 );' .
93
- "\n" . '}';
94
- if ( is_subdomain_install() ) {
95
- $file_string .= "\n" . '$site_url = $domain;';
96
- } else {
97
- $file_string .= "\n" . 'list( $path ) = explode( \'?\', stripslashes( $_SERVER[\'REQUEST_URI\'] ) );' .
98
- "\n" . '$path_parts = explode( \'/\', rtrim( $path, \'/\' ) );' .
99
- "\n" . '$site_url = $domain . ( ! empty( $path_parts[1] ) ? \'/\' . $path_parts[1] : \'\' );';
100
- }
101
-
102
- // Create conditional blocks for each site.
103
- $file_string .= "\n" . 'switch ( $site_url ) {';
104
- foreach ( array_reverse( $cache_configs ) as $filename => $urls ) {
105
- $blog_file = trailingslashit( WP_CONTENT_DIR ) . 'breeze-config/' . $filename . '.php';
106
-
107
- if ( ! is_array( $urls ) ) {
108
- $urls = array( $urls );
109
- }
110
-
111
- if ( empty( $urls ) || empty( $urls[0] ) ) {
112
- continue;
113
- }
114
-
115
- foreach ( $urls as $site_url ) {
116
- $file_string .= "\n\tcase '$site_url':";
117
- }
118
- $file_string .= "\n\t\t\$config = '$blog_file';" .
119
- "\n\t\tbreak;";
120
- }
121
- $file_string .= "\n}";
122
- }
123
-
124
- $file_string .= "\nif ( empty( \$config ) || ! @file_exists( \$config ) ) { return; }" .
125
- "\n\$GLOBALS['breeze_config'] = include \$config;" .
126
- "\n" . 'if ( empty( $GLOBALS[\'breeze_config\'] ) || empty( $GLOBALS[\'breeze_config\'][\'cache_options\'][\'breeze-active\'] ) ) { return; }' .
127
- "\n" . 'if ( @file_exists( \'' . BREEZE_PLUGIN_DIR . 'inc/cache/execute-cache.php\' ) ) {' .
128
- "\n" . ' include_once \'' . BREEZE_PLUGIN_DIR . 'inc/cache/execute-cache.php\';' .
129
- "\n" . '}' . "\n";
130
-
131
- return $wp_filesystem->put_contents( $file, $file_string );
132
- }
133
-
134
- /**
135
- * Function write parameter to breeze-config
136
- * @return breeze_Cache
137
- */
138
- public static function write_config_cache(){
139
- $settings = breeze_get_option( 'basic_settings' );
140
- $config = breeze_get_option( 'advanced_settings' );
141
- $ecommerce_exclude_urls = array();
142
-
143
- $storage = array(
144
- 'homepage' => get_site_url(),
145
- 'cache_options' => $settings,
146
- 'disable_per_adminuser' => 0,
147
- 'exclude_url' => array(),
148
- );
149
-
150
- if(is_multisite()){
151
- $storage['blog_id'] = get_current_blog_id();
152
- }
153
-
154
- if( class_exists('WooCommerce')){
155
- $ecommerce_exclude_urls = Breeze_Ecommerce_Cache::factory()->ecommerce_exclude_pages();
156
- }
157
- if(!empty($settings['breeze-disable-admin'])){
158
- $storage['disable_per_adminuser'] = $settings['breeze-disable-admin'];
159
- }
160
-
161
- $storage['exclude_url'] = array_merge(
162
- $ecommerce_exclude_urls,
163
- ! empty( $config['breeze-exclude-urls'] ) ? $config['breeze-exclude-urls'] : array()
164
- );
165
-
166
- $saved_pages = get_option( 'breeze_exclude_url_pages', array() );
167
-
168
- if ( ! empty( $saved_pages ) ) {
169
- $saved_pages_urls = array();
170
- foreach ( $saved_pages as $page_id ) {
171
- $saved_pages_urls[] = get_permalink( $page_id );
172
- }
173
-
174
- $saved_pages_urls = array_unique( $saved_pages_urls );
175
-
176
- $storage['exclude_url'] = array_merge(
177
- $saved_pages_urls,
178
- ! empty( $config['breeze-exclude-urls'] ) ? $config['breeze-exclude-urls'] : array()
179
- );
180
- }
181
-
182
-
183
- if( class_exists('WC_Facebook_Loader')){
184
- $woocommerce_fb_feed_link = Breeze_Ecommerce_Cache::factory()->wc_facebook_feed();
185
-
186
- if(!empty($woocommerce_fb_feed_link)){
187
- $storage['exclude_url'] = array_merge(
188
- $woocommerce_fb_feed_link,
189
- ! empty( $config['breeze-exclude-urls'] ) ? $config['breeze-exclude-urls'] : array()
190
- );
191
- }
192
- }
193
-
194
- return self::write_config( $storage );
195
- }
196
-
197
- /*
198
- * create file config storage parameter used for cache
199
- */
200
- public static function write_config( $config ) {
201
- global $wp_filesystem;
202
-
203
- $config_dir = trailingslashit( WP_CONTENT_DIR ) . 'breeze-config';
204
- $filename = 'breeze-config';
205
- if ( is_multisite() && ! is_network_admin() ) {
206
- $filename .= '-' . get_current_blog_id();
207
- }
208
-
209
- $config_file = $config_dir . DIRECTORY_SEPARATOR . $filename . '.php';
210
-
211
- if ( is_multisite() && ! is_network_admin() && breeze_does_inherit_settings() ) {
212
- // Site inherits network-level setting, do not create separate configuration file and remove existing configuration file.
213
- if ( $wp_filesystem->exists( $config_file ) ) {
214
- $wp_filesystem->delete( $config_file, true );
215
- }
216
- return;
217
- }
218
-
219
- $wp_filesystem->mkdir( $config_dir );
220
-
221
- $config_file_string = '<?php ' . "\n\r" . "defined( 'ABSPATH' ) || exit;" . "\n\r" . 'return ' . var_export( $config, true ) . '; ' . "\n\r";
222
-
223
-
224
- return $wp_filesystem->put_contents( $config_file, $config_file_string );
225
- }
226
- //turn on / off wp cache
227
- public function toggle_caching( $status ) {
228
-
229
- global $wp_filesystem;
230
- if ( defined( 'WP_CACHE' ) && WP_CACHE === $status ) {
231
- return;
232
- }
233
-
234
- // Lets look 4 levels deep for wp-config.php
235
- $levels = 4;
236
-
237
- $file = '/wp-config.php';
238
- $config_path = false;
239
-
240
- for ( $i = 1; $i <= 3; $i++ ) {
241
- if ( $i > 1 ) {
242
- $file = '/..' . $file;
243
- }
244
-
245
- if ( $wp_filesystem->exists( untrailingslashit( ABSPATH ) . $file ) ) {
246
- $config_path = untrailingslashit( ABSPATH ) . $file;
247
- break;
248
- }
249
- }
250
-
251
- // Couldn't find wp-config.php
252
- if ( ! $config_path ) {
253
- return false;
254
- }
255
-
256
- $config_file_string = $wp_filesystem->get_contents( $config_path );
257
-
258
- // Config file is empty. Maybe couldn't read it?
259
- if ( empty( $config_file_string ) ) {
260
- return false;
261
- }
262
-
263
- $config_file = preg_split( "#(\n|\r)#", $config_file_string );
264
- $line_key = false;
265
-
266
- foreach ( $config_file as $key => $line ) {
267
- if ( ! preg_match( '/^\s*define\(\s*(\'|")([A-Z_]+)(\'|")(.*)/', $line, $match ) ) {
268
- continue;
269
- }
270
-
271
- if ( $match[2] == 'WP_CACHE' ) {
272
- $line_key = $key;
273
- }
274
- }
275
-
276
- if ( $line_key !== false ) {
277
- unset( $config_file[ $line_key ] );
278
- }
279
-
280
- $status_string = ( $status ) ? 'true' : 'false';
281
-
282
- array_shift( $config_file );
283
- array_unshift( $config_file, '<?php', "define( 'WP_CACHE', $status_string ); " );
284
-
285
- foreach ( $config_file as $key => $line ) {
286
- if ( '' === $line ) {
287
- unset( $config_file[$key] );
288
- }
289
- }
290
-
291
- if ( ! $wp_filesystem->put_contents( $config_path, implode( PHP_EOL, $config_file ) ) ) {
292
- return false;
293
- }
294
-
295
- return true;
296
- }
297
- //delete file for clean up
298
-
299
- public function clean_up() {
300
-
301
- global $wp_filesystem;
302
- $file = untrailingslashit( WP_CONTENT_DIR ) . '/advanced-cache.php';
303
-
304
- $ret = true;
305
-
306
- if ( ! $wp_filesystem->delete( $file ) ) {
307
- $ret = false;
308
- }
309
-
310
- $folder = untrailingslashit( breeze_get_cache_base_path() );
311
-
312
- if ( ! $wp_filesystem->delete( $folder, true ) ) {
313
- $ret = false;
314
- }
315
-
316
- $folder = untrailingslashit( WP_CONTENT_DIR ) . '/cache/breeze-minification';
317
-
318
- if ( ! $wp_filesystem->delete( $folder, true ) ) {
319
- $ret = false;
320
- }
321
-
322
- return $ret;
323
- }
324
-
325
- //delete config file
326
- public function clean_config() {
327
-
328
- global $wp_filesystem;
329
-
330
- $folder = untrailingslashit( WP_CONTENT_DIR ) . '/breeze-config';
331
- return $wp_filesystem->delete( $folder, true );
332
-
333
- return true;
334
- }
335
-
336
-
337
- public static function factory() {
338
-
339
- static $instance;
340
-
341
- if ( ! $instance ) {
342
- $instance = new self();
343
- }
344
-
345
- return $instance;
346
- }
347
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ //Based on some work of simple-cache
22
+ if ( ! defined( 'ABSPATH' ) ) {
23
+ exit;
24
+ }
25
+
26
+ class Breeze_ConfigCache {
27
+
28
+ /**
29
+ * Create advanced-cache file
30
+ */
31
+ public function write() {
32
+ global $wp_filesystem;
33
+
34
+ $file = trailingslashit( WP_CONTENT_DIR ) . '/advanced-cache.php';
35
+
36
+ // Create array of configuration files and their corresponding sites' URLs.
37
+ $cache_configs = array(
38
+ 'breeze-config' => array(),
39
+ );
40
+ if ( is_multisite() ) {
41
+ // This is a multisite install, loop through all subsites.
42
+ $blogs = get_sites(
43
+ array(
44
+ 'fields' => 'ids',
45
+ )
46
+ );
47
+
48
+ foreach ( $blogs as $blog_id ) {
49
+ switch_to_blog( $blog_id );
50
+ $config = breeze_get_option( 'basic_settings' );
51
+ if ( ! empty( $config['breeze-active'] ) ) {
52
+ $inherit_option = get_option( 'breeze_inherit_settings' );
53
+
54
+ if ( '0' === $inherit_option ) {
55
+ // Site uses own (custom) configuration.
56
+ $cache_configs[ "breeze-config-{$blog_id}" ] = preg_replace( '(^https?://)', '', site_url() );
57
+ } else {
58
+ // Site uses global configuration.
59
+ $cache_configs['breeze-config'][] = preg_replace( '(^https?://)', '', site_url() );
60
+ }
61
+ }
62
+ restore_current_blog();
63
+ }
64
+ } else {
65
+ $config = breeze_get_option( 'basic_settings' );
66
+
67
+ if ( ! empty( $config['breeze-active'] ) ) {
68
+ $cache_configs['breeze-config'][] = preg_replace( '(^https?://)', '', site_url() );
69
+ }
70
+ }
71
+
72
+ if ( empty( $cache_configs ) || ( 1 === count( $cache_configs ) && empty( $cache_configs['breeze-config'] ) ) ) {
73
+ // No sites with caching enabled.
74
+ $this->clean_config();
75
+ return;
76
+ } else {
77
+ $file_string = '<?php ' .
78
+ "\n\r" . 'defined( \'ABSPATH\' ) || exit;' .
79
+ "\n\r" . 'define( \'BREEZE_ADVANCED_CACHE\', true );' .
80
+ "\n\r" . 'if ( is_admin() ) { return; }' .
81
+ "\n\r" . 'if ( ! @file_exists( \'' . BREEZE_PLUGIN_DIR . 'breeze.php\' ) ) { return; }';
82
+ }
83
+
84
+ if ( 1 === count( $cache_configs ) ) {
85
+ // Only 1 config file available.
86
+ $blog_file = trailingslashit( WP_CONTENT_DIR ) . 'breeze-config/breeze-config.php';
87
+ $file_string .= "\n\$config = '$blog_file';";
88
+ } else {
89
+ // Multiple configuration files, load appropriate one by comparing URLs.
90
+ $file_string .= "\n\r" . '$domain = strtolower( stripslashes( $_SERVER[\'HTTP_HOST\'] ) );' .
91
+ "\n" . 'if ( substr( $domain, -3 ) == \':80\' ) {' .
92
+ "\n" . ' $domain = substr( $domain, 0, -3 );' .
93
+ "\n" . '} elseif ( substr( $domain, -4 ) == \':443\' ) {' .
94
+ "\n" . ' $domain = substr( $domain, 0, -4 );' .
95
+ "\n" . '}';
96
+ if ( is_subdomain_install() ) {
97
+ $file_string .= "\n" . '$site_url = $domain;';
98
+ } else {
99
+ $file_string .= "\n" . 'list( $path ) = explode( \'?\', stripslashes( $_SERVER[\'REQUEST_URI\'] ) );' .
100
+ "\n" . '$path_parts = explode( \'/\', rtrim( $path, \'/\' ) );' .
101
+ "\n" . '$site_url = $domain . ( ! empty( $path_parts[1] ) ? \'/\' . $path_parts[1] : \'\' );';
102
+ }
103
+
104
+ // Create conditional blocks for each site.
105
+ $file_string .= "\n" . 'function breeze_fetch_configuration_data( $site_url ) {';
106
+ $file_string .= "\n\t" . '$config = array();';
107
+ $file_string .= "\n\t" . 'switch ( $site_url ) {';
108
+ foreach ( array_reverse( $cache_configs ) as $filename => $urls ) {
109
+ $blog_file = trailingslashit( WP_CONTENT_DIR ) . 'breeze-config/' . $filename . '.php';
110
+
111
+ if ( ! is_array( $urls ) ) {
112
+ $urls = array( $urls );
113
+ }
114
+
115
+ if ( empty( $urls ) || empty( $urls[0] ) ) {
116
+ continue;
117
+ }
118
+
119
+ foreach ( $urls as $site_url ) {
120
+ $file_string .= "\n\tcase '$site_url':";
121
+ }
122
+ $file_string .= "\n\t\t\$config = '$blog_file';" .
123
+ "\n\t\tbreak;";
124
+ }
125
+
126
+ $file_string .= "\n\t}";
127
+ $file_string .= "\n\t" . 'return $config;';
128
+ $file_string .= "\n}";
129
+ $file_string .= "\n" . '$config = breeze_fetch_configuration_data( $site_url );';
130
+ $file_string .= "\n" . 'if ( empty( $config ) && false === filter_var( SUBDOMAIN_INSTALL, FILTER_VALIDATE_BOOLEAN ) && true === filter_var( MULTISITE, FILTER_VALIDATE_BOOLEAN ) ) {';
131
+ $file_string .= "\n\t" . '$config = breeze_fetch_configuration_data( $domain );';
132
+ $file_string .= "\n" . '}';
133
+ }
134
+
135
+ $file_string .= "\nif ( empty( \$config ) || ! @file_exists( \$config ) ) { return; }" .
136
+ "\n\$GLOBALS['breeze_config'] = include \$config;" .
137
+ "\n" . 'if ( empty( $GLOBALS[\'breeze_config\'] ) || empty( $GLOBALS[\'breeze_config\'][\'cache_options\'][\'breeze-active\'] ) ) { return; }' .
138
+ "\n" . 'if ( @file_exists( \'' . BREEZE_PLUGIN_DIR . 'inc/cache/execute-cache.php\' ) ) {' .
139
+ "\n" . ' include_once \'' . BREEZE_PLUGIN_DIR . 'inc/cache/execute-cache.php\';' .
140
+ "\n" . '}' . "\n";
141
+
142
+ return $wp_filesystem->put_contents( $file, $file_string );
143
+ }
144
+
145
+ /**
146
+ * Function write parameter to breeze-config.
147
+ *
148
+ * @param bool $create_root_config Used in multisite, to reset/create breeze-config.php file
149
+ */
150
+ public static function write_config_cache( $create_root_config = false ) {
151
+
152
+ if ( true === $create_root_config ) {
153
+ $network_id = get_current_network_id();
154
+ $settings = get_network_option( $network_id, 'breeze_basic_settings' );
155
+ $config = get_network_option( $network_id, 'breeze_advanced_settings' );
156
+ $homepage_url = network_site_url();
157
+ } else {
158
+ $settings = breeze_get_option( 'basic_settings' );
159
+ $config = breeze_get_option( 'advanced_settings' );
160
+ $homepage_url = get_site_url();
161
+ }
162
+
163
+ $ecommerce_exclude_urls = array();
164
+
165
+ $storage = array(
166
+ 'homepage' => $homepage_url,
167
+ 'cache_options' => $settings,
168
+ 'disable_per_adminuser' => 0,
169
+ 'exclude_url' => array(),
170
+ );
171
+
172
+ if ( is_multisite() ) {
173
+ $storage['blog_id'] = get_current_blog_id();
174
+ }
175
+
176
+ if ( class_exists( 'WooCommerce' ) ) {
177
+ $ecommerce_exclude_urls = Breeze_Ecommerce_Cache::factory()->ecommerce_exclude_pages();
178
+ }
179
+
180
+ if ( function_exists( 'EDD' ) ) {
181
+ $exclude_edd_pages = Breeze_Ecommerce_Cache::factory()->exclude_edd_pages();
182
+
183
+ if ( ! empty( $exclude_edd_pages ) ) {
184
+ $ecommerce_exclude_urls = array_merge( $exclude_edd_pages, $ecommerce_exclude_urls );
185
+ }
186
+
187
+ /**
188
+ * Remove Easy Digital Downloads Software Licensing endpoint from cache
189
+ */
190
+ if ( class_exists( 'EDD_Software_Licensing' ) && defined( 'EDD_SL_VERSION' ) ) {
191
+ $ecommerce_exclude_urls[] = '/edd-sl/*';
192
+ }
193
+ }
194
+
195
+ /**
196
+ * Give shop
197
+ */
198
+ if ( function_exists( 'give_get_settings' ) ) {
199
+ $exclude_give_pages = Breeze_Ecommerce_Cache::factory()->exclude_give_pages();
200
+
201
+ if ( ! empty( $exclude_give_pages ) ) {
202
+ $ecommerce_exclude_urls = array_merge( $exclude_give_pages, $ecommerce_exclude_urls );
203
+ }
204
+ }
205
+
206
+ /**
207
+ * Big Commerce
208
+ */
209
+ if ( function_exists( 'bigcommerce' ) ) {
210
+ $exclude_bigcommerce_pages = Breeze_Ecommerce_Cache::factory()->exclude_big_commerce_pages();
211
+
212
+ if ( ! empty( $exclude_bigcommerce_pages ) ) {
213
+ $ecommerce_exclude_urls = array_merge( $exclude_bigcommerce_pages, $ecommerce_exclude_urls );
214
+ }
215
+ }
216
+
217
+ /**
218
+ * CartFlows
219
+ */
220
+ if ( class_exists( 'Cartflows_Loader' ) && defined( 'CARTFLOWS_FILE' ) ) {
221
+ $exclude_cartflows_pages = Breeze_Ecommerce_Cache::factory()->exclude_cart_flows_pages();
222
+
223
+ if ( ! empty( $exclude_cartflows_pages ) ) {
224
+ $ecommerce_exclude_urls = array_merge( $exclude_cartflows_pages, $ecommerce_exclude_urls );
225
+ }
226
+ }
227
+
228
+ /**
229
+ * MemberPress
230
+ */
231
+ if ( class_exists( 'MeprJobs' ) && defined( 'MEPR_OPTIONS_SLUG' ) ) {
232
+ $exclude_memberpress_pages = Breeze_Ecommerce_Cache::factory()->exclude_member_press_pages();
233
+
234
+ if ( ! empty( $exclude_memberpress_pages ) ) {
235
+ $ecommerce_exclude_urls = array_merge( $exclude_memberpress_pages, $ecommerce_exclude_urls );
236
+ }
237
+ }
238
+
239
+ /**
240
+ * WP eCommerce
241
+ */
242
+ if ( class_exists( 'WP_eCommerce' ) ) {
243
+ $exclude_wp_ecommerce_pages = Breeze_Ecommerce_Cache::factory()->exclude_wp_e_commerce_pages();
244
+
245
+ if ( ! empty( $exclude_wp_ecommerce_pages ) ) {
246
+ $ecommerce_exclude_urls = array_merge( $exclude_wp_ecommerce_pages, $ecommerce_exclude_urls );
247
+ }
248
+ }
249
+
250
+ /**
251
+ * Ecwid Ecommerce Shopping Cart
252
+ */
253
+ if ( function_exists( 'ecwid_init_integrations' ) && defined( 'ECWID_PLUGIN_DIR' ) ) {
254
+ $exclude_ecwid_pages = Breeze_Ecommerce_Cache::factory()->exclude_ecwid_store_pages();
255
+
256
+ if ( ! empty( $exclude_ecwid_pages ) ) {
257
+ $ecommerce_exclude_urls = array_merge( $exclude_ecwid_pages, $ecommerce_exclude_urls );
258
+ }
259
+ }
260
+
261
+ /**
262
+ * WP EasyCart
263
+ */
264
+ if ( defined( 'EC_PUGIN_NAME' ) && function_exists( 'wpeasycart_load_startup' ) ) {
265
+ $exclude_wp_easy_cart_pages = Breeze_Ecommerce_Cache::factory()->exclude_easy_cart_pages();
266
+
267
+ if ( ! empty( $exclude_wp_easy_cart_pages ) ) {
268
+ $ecommerce_exclude_urls = array_merge( $exclude_wp_easy_cart_pages, $ecommerce_exclude_urls );
269
+ }
270
+ }
271
+
272
+ if ( ! empty( $settings['breeze-disable-admin'] ) ) {
273
+ $storage['disable_per_adminuser'] = $settings['breeze-disable-admin'];
274
+ }
275
+
276
+ $storage['exclude_url'] = array_merge(
277
+ $ecommerce_exclude_urls,
278
+ ! empty( $config['breeze-exclude-urls'] ) ? $config['breeze-exclude-urls'] : array()
279
+ );
280
+
281
+ $saved_pages = get_option( 'breeze_exclude_url_pages', array() );
282
+
283
+ if ( ! empty( $saved_pages ) ) {
284
+ $saved_pages_urls = array();
285
+ foreach ( $saved_pages as $page_id ) {
286
+ $saved_pages_urls[] = get_permalink( $page_id );
287
+ }
288
+
289
+ $saved_pages_urls = array_unique( $saved_pages_urls );
290
+
291
+ $storage['exclude_url'] = array_merge(
292
+ $saved_pages_urls,
293
+ ! empty( $config['breeze-exclude-urls'] ) ? $config['breeze-exclude-urls'] : array(),
294
+ $ecommerce_exclude_urls
295
+ );
296
+ }
297
+
298
+ if ( class_exists( 'WC_Facebook_Loader' ) ) {
299
+ $woocommerce_fb_feed_link = Breeze_Ecommerce_Cache::factory()->wc_facebook_feed();
300
+
301
+ if ( ! empty( $woocommerce_fb_feed_link ) ) {
302
+ $storage['exclude_url'] = array_merge(
303
+ $woocommerce_fb_feed_link,
304
+ ! empty( $config['breeze-exclude-urls'] ) ? $config['breeze-exclude-urls'] : array(),
305
+ $ecommerce_exclude_urls
306
+ );
307
+ }
308
+ }
309
+
310
+ return self::write_config( $storage, $create_root_config );
311
+ }
312
+
313
+ /**
314
+ * Create file config storage parameter used for cache.
315
+ *
316
+ * @param array $config Options array.
317
+ * @param bool $create_root_config Used in multisite, to reset/create breeze-config.php file
318
+ */
319
+ public static function write_config( $config, $create_root_config = false ) {
320
+ global $wp_filesystem;
321
+
322
+ if ( empty( $wp_filesystem ) ) {
323
+ require_once( ABSPATH . '/wp-admin/includes/file.php' );
324
+ WP_Filesystem();
325
+ }
326
+
327
+ $config_dir = trailingslashit( WP_CONTENT_DIR ) . 'breeze-config';
328
+ $filename = 'breeze-config';
329
+ if ( false === $create_root_config && ( is_multisite() && ! is_network_admin() ) ) {
330
+ $filename .= '-' . get_current_blog_id();
331
+ }
332
+
333
+ $config_file = $config_dir . DIRECTORY_SEPARATOR . $filename . '.php';
334
+
335
+ if ( is_multisite() && ! is_network_admin() && breeze_does_inherit_settings() ) {
336
+ // Site inherits network-level setting, do not create separate configuration file and remove existing configuration file.
337
+ if ( $wp_filesystem->exists( $config_file ) ) {
338
+ $wp_filesystem->delete( $config_file, true );
339
+ }
340
+ return;
341
+ }
342
+
343
+ $wp_filesystem->mkdir( $config_dir );
344
+
345
+ $config_file_string = '<?php ' . "\n\r" . "defined( 'ABSPATH' ) || exit;" . "\n\r" . 'return ' . var_export( $config, true ) . '; ' . "\n\r";
346
+
347
+ return $wp_filesystem->put_contents( $config_file, $config_file_string );
348
+ }
349
+
350
+ /**
351
+ * Turn on / off wp cache.
352
+ *
353
+ * @param bool $status If WP Cache is enabled or not.
354
+ *
355
+ * @return bool|void
356
+ */
357
+ public function toggle_caching( $status ) {
358
+
359
+ global $wp_filesystem;
360
+ if ( defined( 'WP_CACHE' ) && WP_CACHE === $status ) {
361
+ return;
362
+ }
363
+
364
+ // Lets look 4 levels deep for wp-config.php
365
+ $levels = 4;
366
+
367
+ $file = '/wp-config.php';
368
+ $config_path = false;
369
+
370
+ for ( $i = 1; $i <= 3; $i++ ) {
371
+ if ( $i > 1 ) {
372
+ $file = '/..' . $file;
373
+ }
374
+
375
+ if ( $wp_filesystem->exists( untrailingslashit( ABSPATH ) . $file ) ) {
376
+ $config_path = untrailingslashit( ABSPATH ) . $file;
377
+ break;
378
+ }
379
+ }
380
+
381
+ // Couldn't find wp-config.php
382
+ if ( ! $config_path ) {
383
+ return false;
384
+ }
385
+
386
+ $config_file_string = $wp_filesystem->get_contents( $config_path );
387
+
388
+ // Config file is empty. Maybe couldn't read it?
389
+ if ( empty( $config_file_string ) ) {
390
+ return false;
391
+ }
392
+
393
+ $config_file = preg_split( "#(\n|\r)#", $config_file_string );
394
+ $line_key = false;
395
+
396
+ foreach ( $config_file as $key => $line ) {
397
+ if ( ! preg_match( '/^\s*define\(\s*(\'|")([A-Z_]+)(\'|")(.*)/', $line, $match ) ) {
398
+ continue;
399
+ }
400
+
401
+ if ( 'WP_CACHE' === $match[2] ) {
402
+ $line_key = $key;
403
+ }
404
+ }
405
+
406
+ if ( false !== $line_key ) {
407
+ unset( $config_file[ $line_key ] );
408
+ }
409
+
410
+ $status_string = ( $status ) ? 'true' : 'false';
411
+
412
+ array_shift( $config_file );
413
+ array_unshift( $config_file, '<?php', "define( 'WP_CACHE', $status_string ); " );
414
+
415
+ foreach ( $config_file as $key => $line ) {
416
+ if ( '' === $line ) {
417
+ unset( $config_file[ $key ] );
418
+ }
419
+ }
420
+
421
+ if ( ! $wp_filesystem->put_contents( $config_path, implode( PHP_EOL, $config_file ) ) ) {
422
+ return false;
423
+ }
424
+
425
+ return true;
426
+ }
427
+
428
+ /**
429
+ * Delete file for clean up.
430
+ *
431
+ * @return bool
432
+ */
433
+ public function clean_up() {
434
+
435
+ global $wp_filesystem;
436
+ $file = untrailingslashit( WP_CONTENT_DIR ) . '/advanced-cache.php';
437
+
438
+ $ret = true;
439
+
440
+ if ( ! $wp_filesystem->delete( $file ) ) {
441
+ $ret = false;
442
+ }
443
+
444
+ $folder = untrailingslashit( breeze_get_cache_base_path() );
445
+
446
+ if ( ! $wp_filesystem->delete( $folder, true ) ) {
447
+ $ret = false;
448
+ }
449
+
450
+ $folder = untrailingslashit( WP_CONTENT_DIR ) . '/cache/breeze-minification';
451
+
452
+ if ( ! $wp_filesystem->delete( $folder, true ) ) {
453
+ $ret = false;
454
+ }
455
+
456
+ return $ret;
457
+ }
458
+
459
+ /**
460
+ * Delete config file.
461
+ *
462
+ * @return mixed
463
+ */
464
+ public function clean_config() {
465
+
466
+ global $wp_filesystem;
467
+
468
+ $folder = untrailingslashit( WP_CONTENT_DIR ) . '/breeze-config';
469
+ return $wp_filesystem->delete( $folder, true );
470
+
471
+ return true;
472
+ }
473
+
474
+ /**
475
+ * Singleton instance.
476
+ *
477
+ * @return Breeze_ConfigCache
478
+ */
479
+ public static function factory() {
480
+
481
+ static $instance;
482
+
483
+ if ( ! $instance ) {
484
+ $instance = new self();
485
+ }
486
+
487
+ return $instance;
488
+ }
489
+ }
inc/cache/ecommerce-cache.php CHANGED
@@ -1,188 +1,639 @@
1
- <?php
2
- defined( 'ABSPATH' ) or die('Not allow!');
3
-
4
- /*
5
- * Class for E-commerce Cache
6
- */
7
- class Breeze_Ecommerce_Cache {
8
- public function __construct() {
9
- add_action( 'activated_plugin', array($this,'detect_ecommerce_activation') );
10
- add_action( 'deactivated_plugin', array($this,'detect_ecommerce_deactivation') );
11
- add_action( 'wp_loaded', array($this,'update_ecommerce_activation') );
12
- }
13
-
14
- // After woocommerce active,merge array disable page config
15
- public function detect_ecommerce_activation($plugin){
16
- if( 'woocommerce/woocommerce.php' == $plugin){
17
- update_option('breeze_ecommerce_detect',1);
18
- }
19
- }
20
-
21
- // Delete option detect when deactivate woo
22
- public function detect_ecommerce_deactivation($plugin){
23
- if( 'woocommerce/woocommerce.php' == $plugin){
24
- delete_option('breeze_ecommerce_detect');
25
- }
26
- }
27
-
28
- // Update option when Woocimmerce active
29
- public function update_ecommerce_activation() {
30
- $check = get_option('breeze_ecommerce_detect');
31
- if( stripos($_SERVER['REQUEST_URI'],'wc-setup&step=locale') !== false){
32
- global $wp_filesystem;
33
- if ( empty( $wp_filesystem ) ) {
34
- require_once( ABSPATH . '/wp-admin/includes/file.php' );
35
- WP_Filesystem();
36
- }
37
- Breeze_ConfigCache::write_config_cache();
38
- }
39
- if (!empty($check)) {
40
- global $wp_filesystem;
41
- if ( empty( $wp_filesystem ) ) {
42
- require_once( ABSPATH . '/wp-admin/includes/file.php' );
43
- WP_Filesystem();
44
- }
45
- Breeze_ConfigCache::write_config_cache();
46
- update_option('breeze_ecommerce_detect', 0);
47
- }
48
- }
49
-
50
- /**
51
- * Exclude pages of e-commerce from cache
52
- */
53
- public function ecommerce_exclude_pages(){
54
- $urls = array();
55
- $regex = '*';
56
-
57
- if(class_exists('WooCommerce') && function_exists('wc_get_page_id')){
58
- $cardId = wc_get_page_id('cart');
59
- $checkoutId = wc_get_page_id('checkout');
60
- $myaccountId = wc_get_page_id('myaccount');
61
-
62
- if($cardId > 0){
63
- $urls[] = $this->get_basic_urls($cardId);
64
- // Get url through multi-languages plugin
65
- $urls = $this->get_translate_urls($urls, $cardId);
66
- }
67
-
68
- if($checkoutId > 0){
69
- $urls[] = $this->get_basic_urls($checkoutId , $regex);
70
- // Get url through multi-languages plugin
71
- $urls = $this->get_translate_urls($urls, $checkoutId, $regex );
72
- }
73
-
74
- if($myaccountId > 0){
75
- $urls[] = $this->get_basic_urls($myaccountId , $regex);
76
- // Get url through multi-languages plugin
77
- $urls = $this->get_translate_urls($urls, $myaccountId, $regex );
78
- }
79
-
80
- // Process urls to return
81
- $urls = array_unique($urls);
82
- $urls = array_map(array($this,'rtrim_urls'),$urls);
83
- }
84
-
85
- return $urls;
86
- }
87
-
88
- /**
89
- * Removes from cache WooCommerce Facebook Product Feed.
90
- *
91
- * @return array
92
- * @since 1.1.8
93
- * @access public
94
- */
95
- public function wc_facebook_feed() {
96
- $urls = array();
97
- if ( class_exists( 'WC_Facebook_Loader' ) ) {
98
- $urls[] = SkyVerge\WooCommerce\Facebook\Products\Feed::get_feed_data_url();
99
- }
100
-
101
- return $urls;
102
- }
103
- /*
104
- * Return basic url without translate plugin
105
- */
106
- public function get_basic_urls($postID , $regex = null){
107
- $permalink = get_option('permalink_structure');
108
-
109
- if(!empty($permalink)) {
110
- // Custom URL structure
111
- $url = parse_url(get_permalink($postID),PHP_URL_PATH);
112
- }else {
113
- $url = get_permalink($postID);
114
- }
115
-
116
- return $url . $regex;
117
- }
118
-
119
- /*
120
- * Return translate url without translate plugin
121
- */
122
-
123
- public function get_translate_urls($urls ,$postID , $regex = null){
124
- // WPML plugin
125
- if ( class_exists('SitePress')){
126
- global $sitepress;
127
- if(isset($sitepress)){
128
- $active_languages = $sitepress->get_active_languages();
129
-
130
- if(!empty($active_languages)){
131
- $languages = array_keys($active_languages);
132
- foreach ($languages as $language){
133
- $translatedId = icl_object_id($postID, 'page', false, $language);
134
-
135
- if(empty($translatedId)) continue;
136
-
137
- $urls[] = $this->get_basic_urls($translatedId,$regex);
138
- }
139
- }
140
- }
141
- }
142
-
143
- // Polylang plugin
144
- if( class_exists('Polylang') && function_exists('pll_languages_list') && function_exists('PLL')){
145
- $translatedId = pll_get_post_translations($postID);
146
-
147
- if(!empty($translatedId)){
148
- foreach ($translatedId as $id){
149
- $urls[] = $this->get_basic_urls($id,$regex);
150
- }
151
- }
152
- }
153
-
154
- // qTranslate-x plugin
155
- require_once (ABSPATH.'wp-admin/includes/plugin.php');
156
- if(is_plugin_active('qtranslate-x/qtranslate.php')){
157
- global $q_config;
158
- if(isset($q_config) && function_exists('qtranxf_convertURL')){
159
- $url = $this->get_basic_urls($postID);
160
-
161
- if(!empty($q_config['enabled_languages'])){
162
- foreach ($q_config['enabled_languages'] as $language){
163
- $urls[] = qtranxf_convertURL( $url, $language , true);
164
- }
165
- }
166
-
167
- }
168
- }
169
-
170
- return $urls;
171
- }
172
-
173
- /*
174
- * Remove '/' chacracter of end url
175
- */
176
- public function rtrim_urls($url){
177
- return rtrim($url,'/');
178
- }
179
-
180
- public static function factory() {
181
- static $instance;
182
-
183
- if ( ! $instance ) {
184
- $instance = new self();
185
- }
186
- return $instance;
187
- }
188
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined( 'ABSPATH' ) or die( 'Not allow!' );
3
+
4
+ /*
5
+ * Class for E-commerce Cache
6
+ */
7
+ class Breeze_Ecommerce_Cache {
8
+ public function __construct() {
9
+ add_action( 'activated_plugin', array( $this, 'detect_ecommerce_activation' ) );
10
+ add_action( 'deactivated_plugin', array( $this, 'detect_ecommerce_deactivation' ) );
11
+ add_action( 'wp_loaded', array( $this, 'update_ecommerce_activation' ) );
12
+ }
13
+
14
+ // After woocommerce active,merge array disable page config
15
+ public function detect_ecommerce_activation( $plugin ) {
16
+ if ( 'woocommerce/woocommerce.php' == $plugin ) {
17
+ update_option( 'breeze_ecommerce_detect', 1 );
18
+ }
19
+ }
20
+
21
+ // Delete option detect when deactivate woo
22
+ public function detect_ecommerce_deactivation( $plugin ) {
23
+ if ( 'woocommerce/woocommerce.php' == $plugin ) {
24
+ delete_option( 'breeze_ecommerce_detect' );
25
+ }
26
+ }
27
+
28
+ // Update option when WooCommerce active
29
+ public function update_ecommerce_activation() {
30
+ $check = get_option( 'breeze_ecommerce_detect' );
31
+ if ( stripos( $_SERVER['REQUEST_URI'], 'wc-setup&step=locale' ) !== false ) {
32
+ global $wp_filesystem;
33
+ if ( empty( $wp_filesystem ) ) {
34
+ require_once( ABSPATH . '/wp-admin/includes/file.php' );
35
+ WP_Filesystem();
36
+ }
37
+ Breeze_ConfigCache::write_config_cache();
38
+ }
39
+ if ( ! empty( $check ) ) {
40
+ global $wp_filesystem;
41
+ if ( empty( $wp_filesystem ) ) {
42
+ require_once( ABSPATH . '/wp-admin/includes/file.php' );
43
+ WP_Filesystem();
44
+ }
45
+ Breeze_ConfigCache::write_config_cache();
46
+ update_option( 'breeze_ecommerce_detect', 0 );
47
+ }
48
+ }
49
+
50
+
51
+ public function exclude_give_pages() {
52
+ $urls = array();
53
+ $regex = '*';
54
+
55
+ if ( function_exists( 'give_get_settings' ) && defined( 'GIVE_VERSION' ) ) {
56
+ $give_shop_settings = give_get_settings();
57
+ if ( ! empty( $give_shop_settings ) ) {
58
+
59
+ if ( isset( $give_shop_settings['success_page'] ) ) {
60
+ $success_page_id = absint( $give_shop_settings['success_page'] );
61
+
62
+ if ( ! empty( $success_page_id ) ) {
63
+ $urls[] = $this->get_basic_urls( $success_page_id, $regex );
64
+ // Get url through multi-languages plugin
65
+ $urls = $this->get_translate_urls( $urls, $success_page_id, $regex );
66
+ }
67
+ }
68
+
69
+ if ( isset( $give_shop_settings['history_page'] ) ) {
70
+ $history_page_id = absint( $give_shop_settings['history_page'] );
71
+
72
+ if ( ! empty( $history_page_id ) ) {
73
+ $urls[] = $this->get_basic_urls( $history_page_id, $regex );
74
+ // Get url through multi-languages plugin
75
+ $urls = $this->get_translate_urls( $urls, $history_page_id, $regex );
76
+ }
77
+ }
78
+
79
+ if ( isset( $give_shop_settings['failure_page'] ) ) {
80
+ $failure_page_id = absint( $give_shop_settings['failure_page'] );
81
+
82
+ if ( ! empty( $failure_page_id ) ) {
83
+ $urls[] = $this->get_basic_urls( $failure_page_id, $regex );
84
+ // Get url through multi-languages plugin
85
+ $urls = $this->get_translate_urls( $urls, $failure_page_id, $regex );
86
+ }
87
+ }
88
+
89
+ // Process urls to return
90
+ if ( ! empty( $urls ) ) {
91
+ $urls = array_unique( $urls );
92
+ $urls = array_map( array( $this, 'rtrim_urls' ), $urls );
93
+ }
94
+ }
95
+ }
96
+
97
+ return $urls;
98
+ }
99
+
100
+ /**
101
+ * Excludes from cache for Easy Digital Downloads pages.
102
+ *
103
+ * @return array
104
+ * @since 1.1.7
105
+ * @access public
106
+ */
107
+ public function exclude_edd_pages() {
108
+ $urls = array();
109
+ $regex = '*';
110
+
111
+ if ( function_exists( 'EDD' ) ) {
112
+ $edd_settings = get_option( 'edd_settings' );
113
+ if ( ! empty( $edd_settings ) && isset( $edd_settings['purchase_page'] ) ) {
114
+ $checkout_page_id = absint( $edd_settings['purchase_page'] );
115
+ if ( $checkout_page_id > 0 ) {
116
+ $urls[] = $this->get_basic_urls( $checkout_page_id, $regex );
117
+ // Get url through multi-languages plugin
118
+ $urls = $this->get_translate_urls( $urls, $checkout_page_id, $regex );
119
+ }
120
+ }
121
+ // Process urls to return
122
+ $urls = array_unique( $urls );
123
+ $urls = array_map( array( $this, 'rtrim_urls' ), $urls );
124
+ }
125
+
126
+ return $urls;
127
+ }
128
+
129
+ /**
130
+ * Excludes from cache for Ecwid Ecommerce Shopping Cart.
131
+ *
132
+ * @return array
133
+ * @since 1.1.7
134
+ * @access public
135
+ */
136
+ public function exclude_ecwid_store_pages() {
137
+ $urls = array();
138
+ $regex = '*';
139
+
140
+ if ( function_exists( 'ecwid_init_integrations' ) && defined( 'ECWID_PLUGIN_DIR' ) ) {
141
+ $ecwid_store_page = get_option( 'ecwid_store_page_id', 0 );
142
+ $ecwid_last_store_page = get_option( 'ecwid_last_store_page_id', 0 );
143
+
144
+ if ( ! empty( $ecwid_store_page ) ) {
145
+ $urls[] = $this->get_basic_urls( $ecwid_store_page, $regex );
146
+ // Get url through multi-languages plugin
147
+ $urls = $this->get_translate_urls( $urls, $ecwid_store_page, $regex );
148
+ }
149
+
150
+ if ( ! empty( $ecwid_last_store_page ) ) {
151
+ $urls[] = $this->get_basic_urls( $ecwid_last_store_page, $regex );
152
+ // Get url through multi-languages plugin
153
+ $urls = $this->get_translate_urls( $urls, $ecwid_last_store_page, $regex );
154
+ }
155
+
156
+ // Process urls to return
157
+ if ( ! empty( $urls ) ) {
158
+ $urls = array_unique( $urls );
159
+ $urls = array_map( array( $this, 'rtrim_urls' ), $urls );
160
+ }
161
+ }
162
+
163
+ return $urls;
164
+ }
165
+
166
+ /**
167
+ * Excludes from cache pages from MemberPress.
168
+ *
169
+ * @return array
170
+ * @since 1.1.7
171
+ * @access public
172
+ */
173
+ public function exclude_member_press_pages() {
174
+ $urls = array();
175
+ $regex = '*';
176
+
177
+ if ( class_exists( 'MeprJobs' ) && defined( 'MEPR_OPTIONS_SLUG' ) ) {
178
+ $member_press_options = get_option( MEPR_OPTIONS_SLUG );
179
+
180
+ if ( ! empty( $member_press_options ) ) {
181
+ $account_page_id = isset( $member_press_options['account_page_id'] ) ? $member_press_options['account_page_id'] : 0;
182
+ $login_page_id = isset( $member_press_options['login_page_id'] ) ? $member_press_options['login_page_id'] : 0;
183
+ $thank_you_page_id = isset( $member_press_options['thankyou_page_id'] ) ? $member_press_options['thankyou_page_id'] : 0;
184
+
185
+ if ( ! empty( $account_page_id ) ) {
186
+ $urls[] = $this->get_basic_urls( $account_page_id, $regex );
187
+ // Get url through multi-languages plugin
188
+ $urls = $this->get_translate_urls( $urls, $account_page_id, $regex );
189
+ }
190
+
191
+ if ( ! empty( $login_page_id ) ) {
192
+ $urls[] = $this->get_basic_urls( $login_page_id, $regex );
193
+ // Get url through multi-languages plugin
194
+ $urls = $this->get_translate_urls( $urls, $login_page_id, $regex );
195
+ }
196
+
197
+ if ( ! empty( $thank_you_page_id ) ) {
198
+ $urls[] = $this->get_basic_urls( $thank_you_page_id, $regex );
199
+ // Get url through multi-languages plugin
200
+ $urls = $this->get_translate_urls( $urls, $thank_you_page_id, $regex );
201
+ }
202
+
203
+ // Process urls to return
204
+ if ( ! empty( $urls ) ) {
205
+ $urls = array_unique( $urls );
206
+ $urls = array_map( array( $this, 'rtrim_urls' ), $urls );
207
+ }
208
+ }
209
+ }
210
+
211
+ return $urls;
212
+ }
213
+
214
+ /**
215
+ * Excludes from cache pages from Funnel Builder by CartFlows – Create High Converting Sales Funnels For WordPress.
216
+ *
217
+ * @return array
218
+ * @since 1.1.7
219
+ * @access public
220
+ */
221
+ public function exclude_cart_flows_pages() {
222
+ $urls = array();
223
+ $regex = '*';
224
+ if ( class_exists( 'Cartflows_Loader' ) && defined( 'CARTFLOWS_FILE' ) ) {
225
+ $cart_flow_settings = get_option( '_cartflows_permalink', '' );
226
+
227
+ if ( ! empty( $cart_flow_settings ) ) {
228
+ $permalink = isset( $cart_flow_settings['permalink'] ) ? trim( $cart_flow_settings['permalink'] ) : '';
229
+ $permalink_flow_base = isset( $cart_flow_settings['permalink_flow_base'] ) ? trim( $cart_flow_settings['permalink_flow_base'] ) : '';
230
+ $permalink_structure = isset( $cart_flow_settings['permalink_structure'] ) ? trim( $cart_flow_settings['permalink_structure'] ) : '';
231
+ if ( $permalink === $permalink_flow_base ) {
232
+ $urls[] = "/{$permalink}/{$regex}";
233
+ } else {
234
+ $urls[] = "/{$permalink}/{$regex}";
235
+ $urls[] = "/{$permalink_flow_base}/{$regex}";
236
+ }
237
+ }
238
+ }
239
+ // Process urls to return
240
+ if ( ! empty( $urls ) ) {
241
+ $urls = array_unique( $urls );
242
+ $urls = array_map( array( $this, 'rtrim_urls' ), $urls );
243
+ }
244
+
245
+ return $urls;
246
+ }
247
+
248
+ /**
249
+ * WP eCommerce pages excluded from cache (cart,checkout...)
250
+ *
251
+ * @return array
252
+ * @since 1.1.7
253
+ * @access public
254
+ */
255
+ public function exclude_wp_e_commerce_pages() {
256
+ $urls = array();
257
+ $regex = '*';
258
+
259
+ if ( class_exists( 'WP_eCommerce' ) ) {
260
+ $e_commerce_settings = get_option( 'wpsc_shortcode_page_ids', '' );
261
+
262
+ if ( ! empty( $e_commerce_settings ) ) {
263
+ $products_page = isset( $e_commerce_settings['[productspage]'] ) ? $e_commerce_settings['[productspage]'] : 0;
264
+ $shopping_cart = isset( $e_commerce_settings['[shoppingcart]'] ) ? $e_commerce_settings['[shoppingcart]'] : 0;
265
+ $transaction_results = isset( $e_commerce_settings['[transactionresults]'] ) ? $e_commerce_settings['[transactionresults]'] : 0;
266
+ $user_log = isset( $e_commerce_settings['[userlog]'] ) ? $e_commerce_settings['[userlog]'] : 0;
267
+
268
+ if ( ! empty( $products_page ) ) {
269
+ $urls[] = $this->get_basic_urls( $products_page, $regex );
270
+ // Get url through multi-languages plugin
271
+ $urls = $this->get_translate_urls( $urls, $products_page, $regex );
272
+ }
273
+
274
+ if ( ! empty( $shopping_cart ) ) {
275
+ $urls[] = $this->get_basic_urls( $shopping_cart, $regex );
276
+ // Get url through multi-languages plugin
277
+ $urls = $this->get_translate_urls( $urls, $shopping_cart, $regex );
278
+ }
279
+
280
+ if ( ! empty( $transaction_results ) ) {
281
+ $urls[] = $this->get_basic_urls( $transaction_results, $regex );
282
+ // Get url through multi-languages plugin
283
+ $urls = $this->get_translate_urls( $urls, $transaction_results, $regex );
284
+ }
285
+
286
+ if ( ! empty( $user_log ) ) {
287
+ $urls[] = $this->get_basic_urls( $user_log, $regex );
288
+ // Get url through multi-languages plugin
289
+ $urls = $this->get_translate_urls( $urls, $user_log, $regex );
290
+ }
291
+
292
+ // Process urls to return
293
+ if ( ! empty( $urls ) ) {
294
+ $urls = array_unique( $urls );
295
+ $urls = array_map( array( $this, 'rtrim_urls' ), $urls );
296
+ }
297
+ }
298
+ }
299
+
300
+ return $urls;
301
+ }
302
+
303
+ /**
304
+ * WP EasyCart plugin pages excluded form cache ( cart,account...)
305
+ * @return array
306
+ * @since 1.1.7
307
+ * @access public
308
+ */
309
+ public function exclude_easy_cart_pages() {
310
+ $urls = array();
311
+ $regex = '*';
312
+ if ( defined( 'EC_PUGIN_NAME' ) && function_exists( 'wpeasycart_load_startup' ) ) {
313
+ $account_page_id = get_option( 'ec_option_accountpage', 0 );
314
+ $cart_page_id = get_option( 'ec_option_cartpage', 0 );
315
+
316
+ if ( ! empty( $account_page_id ) ) {
317
+ $urls[] = $this->get_basic_urls( $account_page_id, $regex );
318
+ // Get url through multi-languages plugin
319
+ $urls = $this->get_translate_urls( $urls, $account_page_id, $regex );
320
+ }
321
+
322
+ /**
323
+ * For EasyCart plugin, the cart and checkout page have the same slug.
324
+ * The only difference is the get value ( e.g. cart/?ec_page=checkout_info )
325
+ */
326
+ if ( ! empty( $cart_page_id ) ) {
327
+ $urls[] = $this->get_basic_urls( $cart_page_id, $regex );
328
+ // Get url through multi-languages plugin
329
+ $urls = $this->get_translate_urls( $urls, $cart_page_id, $regex );
330
+ }
331
+
332
+ // Process urls to return
333
+ if ( ! empty( $urls ) ) {
334
+ $urls = array_unique( $urls );
335
+ $urls = array_map( array( $this, 'rtrim_urls' ), $urls );
336
+ }
337
+ }
338
+
339
+ return $urls;
340
+ }
341
+
342
+ /**
343
+ * Excludes from cache cart,checkout and other important pages for BigCommerce.
344
+ *
345
+ * @return array
346
+ * @since 1.1.7
347
+ * @access public
348
+ */
349
+ public function exclude_big_commerce_pages() {
350
+ $urls = array();
351
+ $regex = '*';
352
+ if ( function_exists( 'bigcommerce' ) ) {
353
+ $bigcommerce_cart_page_id = get_option( 'bigcommerce_cart_page_id', 0 );
354
+ if ( ! empty( $bigcommerce_cart_page_id ) ) {
355
+ $urls[] = $this->get_basic_urls( $bigcommerce_cart_page_id, $regex );
356
+ // Get url through multi-languages plugin
357
+ $urls = $this->get_translate_urls( $urls, $bigcommerce_cart_page_id, $regex );
358
+ }
359
+
360
+ $bigcommerce_checkout_page_id = get_option( 'bigcommerce_checkout_page_id', 0 );
361
+ if ( ! empty( $bigcommerce_checkout_page_id ) ) {
362
+ $urls[] = $this->get_basic_urls( $bigcommerce_checkout_page_id, $regex );
363
+ // Get url through multi-languages plugin
364
+ $urls = $this->get_translate_urls( $urls, $bigcommerce_checkout_page_id, $regex );
365
+ }
366
+
367
+ $bigcommerce_account_page_id = get_option( 'bigcommerce_account_page_id', 0 );
368
+ if ( ! empty( $bigcommerce_account_page_id ) ) {
369
+ $urls[] = $this->get_basic_urls( $bigcommerce_account_page_id, $regex );
370
+ // Get url through multi-languages plugin
371
+ $urls = $this->get_translate_urls( $urls, $bigcommerce_account_page_id, $regex );
372
+ }
373
+
374
+ $bigcommerce_address_page_id = get_option( 'bigcommerce_address_page_id', 0 );
375
+ if ( ! empty( $bigcommerce_address_page_id ) ) {
376
+ $urls[] = $this->get_basic_urls( $bigcommerce_address_page_id, $regex );
377
+ // Get url through multi-languages plugin
378
+ $urls = $this->get_translate_urls( $urls, $bigcommerce_address_page_id, $regex );
379
+ }
380
+
381
+ $bigcommerce_gift_balance_page_id = get_option( 'bigcommerce_gift_balance_page_id', 0 );
382
+ if ( ! empty( $bigcommerce_gift_balance_page_id ) ) {
383
+ $urls[] = $this->get_basic_urls( $bigcommerce_gift_balance_page_id, $regex );
384
+ // Get url through multi-languages plugin
385
+ $urls = $this->get_translate_urls( $urls, $bigcommerce_gift_balance_page_id, $regex );
386
+ }
387
+
388
+ $bigcommerce_gift_certificate_page_id = get_option( 'bigcommerce_gift_certificate_page_id', 0 );
389
+ if ( ! empty( $bigcommerce_gift_certificate_page_id ) ) {
390
+ $urls[] = $this->get_basic_urls( $bigcommerce_gift_certificate_page_id, $regex );
391
+ // Get url through multi-languages plugin
392
+ $urls = $this->get_translate_urls( $urls, $bigcommerce_gift_certificate_page_id, $regex );
393
+ }
394
+
395
+ $bigcommerce_login_page_id = get_option( 'bigcommerce_login_page_id', 0 );
396
+ if ( ! empty( $bigcommerce_login_page_id ) ) {
397
+ $urls[] = $this->get_basic_urls( $bigcommerce_login_page_id, $regex );
398
+ // Get url through multi-languages plugin
399
+ $urls = $this->get_translate_urls( $urls, $bigcommerce_login_page_id, $regex );
400
+ }
401
+
402
+ $bigcommerce_registration_page_id = get_option( 'bigcommerce_registration_page_id', 0 );
403
+ if ( ! empty( $bigcommerce_registration_page_id ) ) {
404
+ $urls[] = $this->get_basic_urls( $bigcommerce_registration_page_id, $regex );
405
+ // Get url through multi-languages plugin
406
+ $urls = $this->get_translate_urls( $urls, $bigcommerce_registration_page_id, $regex );
407
+ }
408
+
409
+ // Process urls to return
410
+ if ( ! empty( $urls ) ) {
411
+ $urls = array_unique( $urls );
412
+ $urls = array_map( array( $this, 'rtrim_urls' ), $urls );
413
+ }
414
+ }
415
+
416
+ return $urls;
417
+ }
418
+
419
+ /**
420
+ * Exclude pages of e-commerce from cache
421
+ */
422
+ public function ecommerce_exclude_pages() {
423
+ $urls = array();
424
+ $regex = '*';
425
+
426
+ if ( class_exists( 'WooCommerce' ) && function_exists( 'wc_get_page_id' ) ) {
427
+ $cardId = wc_get_page_id( 'cart' );
428
+ $checkoutId = wc_get_page_id( 'checkout' );
429
+ $myaccountId = wc_get_page_id( 'myaccount' );
430
+
431
+ if ( $cardId > 0 ) {
432
+ $urls[] = $this->get_basic_urls( $cardId, $regex );
433
+ // Get url through multi-languages plugin
434
+ $urls = $this->get_translate_urls( $urls, $cardId, $regex );
435
+ }
436
+
437
+ if ( $checkoutId > 0 ) {
438
+ $urls[] = $this->get_basic_urls( $checkoutId, $regex );
439
+ // Get url through multi-languages plugin
440
+ $urls = $this->get_translate_urls( $urls, $checkoutId, $regex );
441
+ }
442
+
443
+ if ( $myaccountId > 0 ) {
444
+ $urls[] = $this->get_basic_urls( $myaccountId, $regex );
445
+ // Get url through multi-languages plugin
446
+ $urls = $this->get_translate_urls( $urls, $myaccountId, $regex );
447
+ }
448
+
449
+ // Process urls to return
450
+ $urls = array_unique( $urls );
451
+ $urls = array_map( array( $this, 'rtrim_urls' ), $urls );
452
+ }
453
+
454
+ return $urls;
455
+ }
456
+
457
+ /**
458
+ * Removes from cache WooCommerce Facebook Product Feed.
459
+ *
460
+ * @return array
461
+ * @since 1.1.8
462
+ * @access public
463
+ */
464
+ public function wc_facebook_feed() {
465
+ $urls = array();
466
+ if ( class_exists( 'WC_Facebook_Loader' ) ) {
467
+ $urls[] = SkyVerge\WooCommerce\Facebook\Products\Feed::get_feed_data_url();
468
+ }
469
+
470
+ return $urls;
471
+ }
472
+ /*
473
+ * Return basic url without translate plugin
474
+ */
475
+ public function get_basic_urls( $postID, $regex = null ) {
476
+ $permalink = get_option( 'permalink_structure' );
477
+
478
+ if ( ! empty( $permalink ) ) {
479
+ // Custom URL structure
480
+ $url = parse_url( get_permalink( $postID ), PHP_URL_PATH );
481
+ } else {
482
+ $url = get_permalink( $postID );
483
+ }
484
+
485
+ return $url . $regex;
486
+ }
487
+
488
+ /*
489
+ * Return translate url without translate plugin
490
+ */
491
+
492
+ public function get_translate_urls( $urls, $postID, $regex = null ) {
493
+
494
+ // WPML plugins
495
+ if ( class_exists( 'SitePress' ) ) {
496
+ global $sitepress;
497
+ if ( isset( $sitepress ) ) {
498
+ $active_languages = $sitepress->get_active_languages();
499
+
500
+ if ( ! empty( $active_languages ) ) {
501
+ $languages = array_keys( $active_languages );
502
+ foreach ( $languages as $language ) {
503
+ $translatedId = icl_object_id( $postID, 'page', false, $language );
504
+
505
+ if ( empty( $translatedId ) ) {
506
+ continue;
507
+ }
508
+
509
+ $urls[] = $this->get_basic_urls( $translatedId, $regex );
510
+ }
511
+ }
512
+ }
513
+ }
514
+
515
+ // Polylang plugin
516
+ if ( class_exists( 'Polylang' ) && function_exists( 'pll_languages_list' ) && function_exists( 'PLL' ) ) {
517
+ $translatedId = pll_get_post_translations( $postID );
518
+
519
+ if ( ! empty( $translatedId ) ) {
520
+ foreach ( $translatedId as $id ) {
521
+ $urls[] = $this->get_basic_urls( $id, $regex );
522
+ }
523
+ }
524
+ }
525
+
526
+ // qTranslate-x plugin
527
+ require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
528
+ if ( is_plugin_active( 'qtranslate-x/qtranslate.php' ) ) {
529
+ global $q_config;
530
+ if ( isset( $q_config ) && function_exists( 'qtranxf_convertURL' ) ) {
531
+ $url = $this->get_basic_urls( $postID );
532
+
533
+ if ( ! empty( $q_config['enabled_languages'] ) ) {
534
+ foreach ( $q_config['enabled_languages'] as $language ) {
535
+ $urls[] = qtranxf_convertURL( $url, $language, true );
536
+ }
537
+ }
538
+ }
539
+ }
540
+
541
+ // WPGlobus Plugin
542
+ if ( class_exists( 'WPGlobus' ) && class_exists( 'WPGlobus_Utils' ) ) {
543
+ $enabled_languages = apply_filters( 'wpglobus_extra_languages', WPGlobus::Config()->enabled_languages, WPGlobus::Config()->language );
544
+ $default_permalink = get_permalink( $postID );
545
+ $config = null;
546
+
547
+ if ( ! empty( $default_permalink ) ) {
548
+
549
+ foreach ( $enabled_languages as $language ) {
550
+
551
+ // Skip default language, and loop for other languages.
552
+ if ( $language != WPGlobus::Config()->language ) {
553
+
554
+ if ( null === $config ) {
555
+ // @codeCoverageIgnoreStart
556
+ $config = WPGlobus::Config();
557
+ }
558
+
559
+ $urls[] = WPGlobus_Utils::localize_url( $default_permalink, $language, $config );
560
+ }
561
+ }
562
+ }
563
+ }
564
+
565
+ // TranslatePress Plugin
566
+ if ( class_exists( 'TRP_Translate_Press' ) ) {
567
+ global $TRP_LANGUAGE;
568
+
569
+ /**
570
+ * @see TRP_Url_Converter::get_url_for_language
571
+ * @see TRP_Machine_Translator::translate
572
+ */
573
+ $current_language = array();
574
+ $other_languages = array();
575
+ $page_link = get_permalink( $postID );
576
+
577
+ $trp = TRP_Translate_Press::get_trp_instance();
578
+
579
+ $trp_languages = $trp->get_component( 'languages' );
580
+ $trp_settings = $trp->get_component( 'settings' );
581
+ $published_languages = $trp_languages->get_language_names( $trp_settings->get_settings()['publish-languages'] );
582
+ $url_converter = $trp->get_component( 'url_converter' );
583
+
584
+ foreach ( $published_languages as $code => $name ) {
585
+ if ( $code == $TRP_LANGUAGE ) {
586
+ $current_language['code'] = $code;
587
+ $current_language['name'] = $name;
588
+ } else {
589
+ $other_languages[ $code ] = $name;
590
+ }
591
+ }
592
+
593
+ foreach ( $other_languages as $code => $name ) {
594
+
595
+ $url_obj = new \TranslatePress\Uri( $page_link );
596
+ $processed_permalink = get_permalink( $postID );
597
+
598
+ if ( $url_obj->isSchemeless() ) {
599
+ $arguments = str_replace( trailingslashit( $processed_permalink ), '', trailingslashit( trailingslashit( home_url() ) . ltrim( $page_link, '/' ) ) );
600
+ } else {
601
+ $arguments = str_replace( $processed_permalink, '', $page_link );
602
+ }
603
+ if ( $arguments == $page_link ) {
604
+ $arguments = '';
605
+ }
606
+
607
+ if ( null === $url_converter->get_lang_from_url_string( $page_link ) ) {
608
+ $abs_home_url_obj = new \TranslatePress\Uri( $url_converter->get_abs_home() );
609
+ $new_url_obj = $url_obj;
610
+ $abs_home_considered_path = trim( str_replace( $abs_home_url_obj->getPath(), '', $url_obj->getPath() ), '/' );
611
+ $new_url_obj->setPath( trailingslashit( trailingslashit( $abs_home_url_obj->getPath() ) . trailingslashit( $url_converter->get_url_slug( $code ) ) . $abs_home_considered_path ) );
612
+ $new_url = $new_url_obj->getUri();
613
+ if ( ! empty( $new_url ) ) {
614
+ $urls[] = str_replace( $abs_home_url_obj->getUri(), '', $new_url );
615
+ }
616
+ }
617
+ }
618
+ }
619
+
620
+ return $urls;
621
+ }
622
+
623
+ /*
624
+ * Remove '/' chacracter of end url
625
+ */
626
+ public function rtrim_urls( $url ) {
627
+ return rtrim( $url, '/' );
628
+ }
629
+
630
+ public static function factory() {
631
+ static $instance;
632
+
633
+ if ( ! $instance ) {
634
+ $instance = new self();
635
+ }
636
+
637
+ return $instance;
638
+ }
639
+ }
inc/cache/execute-cache.php CHANGED
@@ -1,413 +1,498 @@
1
- <?php
2
- /*
3
- * Based on some work of https://github.com/tlovett1/simple-cache/blob/master/inc/dropins/file-based-page-cache.php
4
- */
5
- defined( 'ABSPATH' ) || exit;
6
-
7
- // Load helper functions.
8
- require_once dirname( __DIR__ ) . '/functions.php';
9
-
10
- // Include and instantiate the class.
11
- require_once 'Mobile-Detect-2.8.25/Mobile_Detect.php';
12
- $detect = new \Cloudways\Breeze\Mobile_Detect\Mobile_Detect;
13
-
14
- // Don't cache robots.txt or htacesss
15
- if ( strpos( $_SERVER['REQUEST_URI'], 'robots.txt' ) !== false || strpos( $_SERVER['REQUEST_URI'], '.htaccess' ) !== false ) {
16
- return;
17
- }
18
-
19
- if ( strpos( $_SERVER['REQUEST_URI'], 'breeze-minification' ) !== false ) {
20
- return;
21
- }
22
-
23
- // Don't cache non-GET requests
24
- if ( ! isset( $_SERVER['REQUEST_METHOD'] ) || $_SERVER['REQUEST_METHOD'] !== 'GET' ) {
25
- return;
26
- }
27
-
28
- $file_extension = $_SERVER['REQUEST_URI'];
29
- $file_extension = preg_replace( '#^(.*?)\?.*$#', '$1', $file_extension );
30
- $file_extension = trim( preg_replace( '#^.*\.(.*)$#', '$1', $file_extension ) );
31
-
32
- // Don't cache disallowed extensions. Prevents wp-cron.php, xmlrpc.php, etc.
33
- if ( ! preg_match( '#index\.php$#i', $_SERVER['REQUEST_URI'] ) && in_array( $file_extension, array( 'php', 'xml', 'xsl' ) ) ) {
34
- return;
35
- }
36
-
37
- // @TODO: Remove debugging code.
38
- if ( isset( $_GET['debug_config'] ) ) {
39
- var_dump( $GLOBALS['breeze_config'] );
40
- exit;
41
- }
42
- $filename_guest_suffix = '';
43
- $url_path = breeze_get_url_path();
44
- $user_logged = false;
45
-
46
- if ( substr_count( $url_path, '?' ) > 0 ) {
47
- $filename = $url_path . '&guest';
48
- $filename_guest_suffix = '&guest';
49
- } else {
50
- $filename = $url_path . '?guest';
51
- $filename_guest_suffix = '?guest';
52
- }
53
-
54
- // Don't cache
55
- if ( ! empty( $_COOKIE ) ) {
56
- $wp_cookies = array( 'wordpressuser_', 'wordpresspass_', 'wordpress_sec_', 'wordpress_logged_in_' );
57
-
58
- foreach ( $_COOKIE as $key => $value ) {
59
- // Logged in!
60
- if ( strpos( $key, 'wordpress_logged_in_' ) !== false ) {
61
- $user_logged = true;
62
- }
63
-
64
- }
65
-
66
- if ( $user_logged ) {
67
- foreach ( $_COOKIE as $k => $v ) {
68
- if ( strpos( $k, 'wordpress_logged_in_' ) !== false ) {
69
- $nameuser = substr( $v, 0, strpos( $v, '|' ) );
70
- if ( substr_count( $url_path, '?' ) > 0 ) {
71
- $filename = $url_path .'&'. strtolower( $nameuser );
72
- }else{
73
- $filename = $url_path .'?'. strtolower( $nameuser );
74
- }
75
-
76
- }
77
- }
78
- }
79
-
80
- if ( ! empty( $_COOKIE['breeze_commented_posts'] ) ) {
81
- foreach ( $_COOKIE['breeze_commented_posts'] as $path ) {
82
- if ( rtrim( $path, '/' ) === rtrim( $_SERVER['REQUEST_URI'], '/' ) ) {
83
- // User commented on this post
84
- return;
85
- }
86
- }
87
- }
88
- }
89
-
90
- //check disable cache for page
91
- $domain = ( ( ( ! empty( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] !== 'off' ) || $_SERVER['SERVER_PORT'] == 443 ) ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'];
92
- //decode url with russian language
93
- $current_url = $domain . rawurldecode( $_SERVER['REQUEST_URI'] );
94
- $opts_config = $GLOBALS['breeze_config'];
95
- $check_exclude = check_exclude_page( $opts_config, $current_url );
96
- //load cache
97
- if ( ! $check_exclude ) {
98
- $devices = $opts_config['cache_options'];
99
- $X1 = '';
100
- // Detect devices
101
- if ( $detect->isMobile() && ! $detect->isTablet() ) {
102
- // The first X will be D for Desktop cache
103
- // M for Mobile cache
104
- // T for Tablet cache
105
- if ( (int) $devices['breeze-mobile-cache'] == 1 ) {
106
- $X1 = 'D';
107
- $filename .= '_breeze_cache_desktop';
108
- }
109
- if ( (int) $devices['breeze-mobile-cache'] == 2 ) {
110
- $X1 = 'M';
111
- $filename .= '_breeze_cache_mobile';
112
- }
113
-
114
- } else {
115
- if ( (int) $devices['breeze-desktop-cache'] == 1 ) {
116
- $X1 = 'D';
117
- $filename .= '_breeze_cache_desktop';
118
- }
119
- }
120
-
121
- breeze_serve_cache( $filename, $url_path, $X1, $devices );
122
- ob_start( 'breeze_cache' );
123
- } else {
124
- header( 'Cache-Control: no-cache' );
125
- }
126
-
127
- /**
128
- * Cache output before it goes to the browser
129
- *
130
- * @param string $buffer
131
- * @param int $flags
132
- *
133
- * @return string
134
- * @since 1.0
135
- */
136
- function breeze_cache( $buffer, $flags ) {
137
- // No cache for pages without 200 response status
138
- if ( http_response_code() !== 200 ) {
139
- return $buffer;
140
- }
141
-
142
- require_once 'Mobile-Detect-2.8.25/Mobile_Detect.php';
143
- $detect = new \Cloudways\Breeze\Mobile_Detect\Mobile_Detect;
144
- //not cache per administrator if option disable optimization for admin users clicked
145
- if ( ! empty( $GLOBALS['breeze_config'] ) && (int) $GLOBALS['breeze_config']['disable_per_adminuser'] ) {
146
- if ( function_exists( 'is_user_logged_in' ) && is_user_logged_in() ) {
147
- $current_user = wp_get_current_user();
148
- if ( in_array( 'administrator', $current_user->roles ) ) {
149
- return $buffer;
150
- }
151
- }
152
- }
153
-
154
- if ( strlen( $buffer ) < 255 ) {
155
- return $buffer;
156
- }
157
-
158
- // Don't cache search, 404, or password protected
159
- if ( is_404() || is_search() || post_password_required() ) {
160
- return $buffer;
161
- }
162
- global $wp_filesystem;
163
- if ( empty( $wp_filesystem ) ) {
164
- require_once( ABSPATH . '/wp-admin/includes/file.php' );
165
- WP_Filesystem();
166
- }
167
- $url_path = breeze_get_url_path();
168
-
169
- $blog_id_requested = isset( $GLOBALS['breeze_config']['blog_id'] ) ? $GLOBALS['breeze_config']['blog_id'] : 0;
170
- $cache_base_path = breeze_get_cache_base_path( false, $blog_id_requested );
171
-
172
- $path = $cache_base_path . md5( $url_path );
173
-
174
- // Make sure we can read/write files and that proper folders exist
175
- if ( ! wp_mkdir_p( $path ) ) {
176
- // Can not cache!
177
- return $buffer;
178
- }
179
- $path .= '/';
180
-
181
- $modified_time = time(); // Make sure modified time is consistent
182
-
183
- if ( preg_match( '#</html>#i', $buffer ) ) {
184
- $buffer .= "\n<!-- Cache served by breeze CACHE - Last modified: " . gmdate( 'D, d M Y H:i:s', $modified_time ) . " GMT -->\n";
185
- }
186
- $headers = array(
187
- array(
188
- 'name' => 'Content-Length',
189
- 'value' => strlen( $buffer )
190
- ),
191
- array(
192
- 'name' => 'Content-Type',
193
- 'value' => 'text/html; charset=utf-8'
194
- ),
195
- array(
196
- 'name' => 'Last-Modified',
197
- 'value' => gmdate( 'D, d M Y H:i:s', $modified_time ) . ' GMT'
198
- )
199
- );
200
-
201
- if ( ! isset( $_SERVER['HTTP_X_VARNISH'] ) ) {
202
- $headers = array_merge( array(
203
- array(
204
- 'name' => 'Expires',
205
- 'value' => 'Wed, 17 Aug 2005 00:00:00 GMT'
206
- ),
207
- array(
208
- 'name' => 'Cache-Control',
209
- 'value' => 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0'
210
- ),
211
- array(
212
- 'name' => 'Pragma',
213
- 'value' => 'no-cache'
214
- )
215
- ) );
216
- }
217
-
218
- $data = serialize( array( 'body' => $buffer, 'headers' => $headers ) );
219
- //cache per users
220
- if ( is_user_logged_in() ) {
221
- $current_user = wp_get_current_user();
222
- if ( $current_user->user_login ) {
223
-
224
- if ( substr_count( $url_path, '?' ) > 0 ) {
225
- $url_path .= '&'. $current_user->user_login;
226
- }else{
227
- $url_path .= '?'. $current_user->user_login;
228
- }
229
- #$url_path .= $current_user->user_login;
230
- }
231
- } else {
232
- global $filename_guest_suffix;
233
- $url_path .= $filename_guest_suffix;
234
- }
235
- $devices = $GLOBALS['breeze_config']['cache_options'];
236
- // Detect devices
237
- if ( $detect->isMobile() && ! $detect->isTablet() ) {
238
- if ( $devices['breeze-mobile-cache'] == 1 ) {
239
- $X1 = 'D';
240
- $url_path .= '_breeze_cache_desktop';
241
- }
242
- if ( $devices['breeze-mobile-cache'] == 2 ) {
243
- $X1 = 'M';
244
- $url_path .= '_breeze_cache_mobile';
245
- }
246
- } else {
247
- if ( $devices['breeze-desktop-cache'] == 1 ) {
248
- $X1 = 'D';
249
- $url_path .= '_breeze_cache_desktop';
250
- }
251
- }
252
-
253
- if ( strpos( $url_path, '_breeze_cache_' ) !== false ) {
254
- if ( ! empty( $GLOBALS['breeze_config']['cache_options']['breeze-gzip-compression'] ) && function_exists( 'gzencode' ) ) {
255
- $wp_filesystem->put_contents( $path . md5( $url_path . '/index.gzip.html' ) . '.php', $data );
256
- $wp_filesystem->touch( $path . md5( $url_path . '/index.gzip.html' ) . '.php', $modified_time );
257
- } else {
258
- $wp_filesystem->put_contents( $path . md5( $url_path . '/index.html' ) . '.php', $data );
259
- $wp_filesystem->touch( $path . md5( $url_path . '/index.html' ) . '.php', $modified_time );
260
- }
261
- } else {
262
- return $buffer;
263
- }
264
-
265
- //set cache provider header if not exists cache file
266
- header( 'Cache-Provider:CLOUDWAYS-CACHE-' . $X1 . 'C' );
267
-
268
- // Do not send this header in case we are behind a varnish proxy
269
- if ( ! isset( $_SERVER['HTTP_X_VARNISH'] ) ) {
270
- header( 'Cache-Control: no-cache' ); // Check back every time to see if re-download is necessary
271
- }
272
-
273
- header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s', $modified_time ) . ' GMT' );
274
-
275
- if ( function_exists( 'ob_gzhandler' ) && ! empty( $GLOBALS['breeze_config']['cache_options']['breeze-gzip-compression'] ) ) {
276
- $ini_output_compression = ini_get( 'zlib.output_compression' );
277
- $array_values = array( '1', 'On', 'on' );
278
- if ( in_array( $ini_output_compression, $array_values ) ) {
279
- return $buffer;
280
- } else {
281
- return ob_gzhandler( $buffer, $flags );
282
- }
283
- } else {
284
- return $buffer;
285
- }
286
- }
287
-
288
- /**
289
- * Get URL path for caching
290
- *
291
- * @return string
292
- * @since 1.0
293
- */
294
- function breeze_get_url_path() {
295
-
296
- $host = ( isset( $_SERVER['HTTP_HOST'] ) ) ? $_SERVER['HTTP_HOST'] : '';
297
- $domain = ( ( ( ! empty( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] !== 'off' ) || ( ! empty( $_SERVER['SERVER_PORT'] ) && $_SERVER['SERVER_PORT'] == 443 ) ) ? 'https://' : 'http://' );
298
-
299
- return $domain . rtrim( $host, '/' ) . $_SERVER['REQUEST_URI'];
300
- }
301
-
302
- /**
303
- * Optionally serve cache and exit
304
- *
305
- * @since 1.0
306
- */
307
- function breeze_serve_cache( $filename, $url_path, $X1, $opts ) {
308
- if ( strpos( $filename, '_breeze_cache_' ) === false ) {
309
- return;
310
- }
311
-
312
- if ( function_exists( 'gzencode' ) && ! empty( $GLOBALS['breeze_config']['cache_options']['breeze-gzip-compression'] ) ) {
313
- $file_name = md5( $filename . '/index.gzip.html' ) . '.php';
314
- } else {
315
- $file_name = md5( $filename . '/index.html' ) . '.php';
316
- }
317
-
318
- $blog_id_requested = isset( $GLOBALS['breeze_config']['blog_id'] ) ? $GLOBALS['breeze_config']['blog_id'] : 0;
319
- $path = breeze_get_cache_base_path(false, $blog_id_requested) . md5( $url_path ) . '/' . $file_name;
320
-
321
- $modified_time = 0;
322
- if ( file_exists( $path ) ) {
323
- $modified_time = (int) @filemtime( $path );
324
- }
325
-
326
- if ( ! empty( $opts['breeze-browser-cache'] ) && ! empty( $modified_time ) && ! empty( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) && strtotime( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) === $modified_time ) {
327
- header( $_SERVER['SERVER_PROTOCOL'] . ' 304 Not Modified', true, 304 );
328
- exit;
329
- }
330
-
331
- if ( @file_exists( $path ) ) {
332
-
333
- $cacheFile = file_get_contents( $path );
334
-
335
-
336
- if ( $cacheFile != false ) {
337
- $datas = unserialize( $cacheFile );
338
- foreach ( $datas['headers'] as $data ) {
339
- header( $data['name'] . ': ' . $data['value'] );
340
- }
341
- //set cache provider header
342
- header( 'Cache-Provider:CLOUDWAYS-CACHE-' . $X1 . 'E' );
343
-
344
- $client_support_gzip = true;
345
-
346
- //check gzip request from client
347
- if ( isset( $_SERVER['HTTP_ACCEPT_ENCODING'] ) && ( strpos( $_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip' ) === false || strpos( $_SERVER['HTTP_ACCEPT_ENCODING'], 'deflate' ) === false ) ) {
348
- $client_support_gzip = false;
349
- }
350
-
351
- if ( $client_support_gzip && function_exists( 'gzdecode' ) && ! empty( $GLOBALS['breeze_config']['cache_options']['breeze-gzip-compression'] ) ) {
352
- //if file is zip
353
-
354
- $content = gzencode( $datas['body'], 9 );
355
- header( 'Content-Encoding: gzip' );
356
- header( "cache-control: must-revalidate" );
357
- header( 'Content-Length: ' . strlen( $content ) );
358
- header( 'Vary: Accept-Encoding' );
359
- echo $content;
360
- } else {
361
- //render page cache
362
- echo $datas['body'];
363
- }
364
- exit;
365
- }
366
- }
367
- }
368
-
369
- function check_exclude_page( $opts_config, $current_url ) {
370
- $is_feed = breeze_is_feed( $current_url );
371
-
372
- if ( true === $is_feed ) {
373
- return true;
374
- }
375
-
376
-
377
- //check disable cache for page
378
- if ( ! empty( $opts_config['exclude_url'] ) ) {
379
- foreach ( $opts_config['exclude_url'] as $v ) {
380
- // Clear blank character
381
- $v = trim( $v );
382
- if ( preg_match( '/(\&?\/?\(\.?\*\)|\/\*|\*)$/', $v, $matches ) ) {
383
- // End of rules is *, /*, [&][/](*) , [&][/](.*)
384
- $pattent = substr( $v, 0, strpos( $v, $matches[0] ) );
385
- if ( $v[0] == '/' ) {
386
- // A path of exclude url with regex
387
- if ( ( @preg_match( '@' . $pattent . '@', $current_url, $matches ) > 0 ) ) {
388
- return true;
389
- }
390
- } else {
391
- // Full exclude url with regex
392
- if ( strpos( $current_url, $pattent ) !== false ) {
393
- return true;
394
- }
395
- }
396
-
397
- } else {
398
- if ( $v[0] == '/' ) {
399
- // A path of exclude
400
- if ( ( @preg_match( '@' . $v . '@', $current_url, $matches ) > 0 ) ) {
401
- return true;
402
- }
403
- } else { // Whole path
404
- if ( $v == $current_url ) {
405
- return true;
406
- }
407
- }
408
- }
409
- }
410
- }
411
-
412
- return false;
413
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Based on some work of https://github.com/tlovett1/simple-cache/blob/master/inc/dropins/file-based-page-cache.php
4
+ */
5
+ defined( 'ABSPATH' ) || exit;
6
+
7
+ // Load helper functions.
8
+ require_once dirname( __DIR__ ) . '/functions.php';
9
+
10
+ // Include and instantiate the class.
11
+ require_once 'Mobile-Detect-2.8.25/Mobile_Detect.php';
12
+ $detect = new \Cloudways\Breeze\Mobile_Detect\Mobile_Detect;
13
+
14
+ // Don't cache robots.txt or htacesss
15
+ if ( strpos( $_SERVER['REQUEST_URI'], 'robots.txt' ) !== false || strpos( $_SERVER['REQUEST_URI'], '.htaccess' ) !== false ) {
16
+ return;
17
+ }
18
+
19
+ if (
20
+ strpos( $_SERVER['REQUEST_URI'], 'breeze-minification' ) !== false ||
21
+ strpos( $_SERVER['REQUEST_URI'], 'favicon.ico' ) !== false
22
+ ) {
23
+ return;
24
+ }
25
+
26
+ // Don't cache non-GET requests
27
+ if ( ! isset( $_SERVER['REQUEST_METHOD'] ) || 'GET' !== $_SERVER['REQUEST_METHOD'] ) {
28
+ return;
29
+ }
30
+
31
+ $file_extension = $_SERVER['REQUEST_URI'];
32
+ $file_extension = preg_replace( '#^(.*?)\?.*$#', '$1', $file_extension );
33
+ $file_extension = trim( preg_replace( '#^.*\.(.*)$#', '$1', $file_extension ) );
34
+
35
+ // Don't cache disallowed extensions. Prevents wp-cron.php, xmlrpc.php, etc.
36
+ if ( ! preg_match( '#index\.php$#i', $_SERVER['REQUEST_URI'] ) && in_array( $file_extension, array( 'php', 'xml', 'xsl' ) ) ) {
37
+ return;
38
+ }
39
+
40
+ $filename_guest_suffix = '';
41
+ $url_path = breeze_get_url_path();
42
+ $user_logged = false;
43
+
44
+ if ( substr_count( $url_path, '?' ) > 0 ) {
45
+ $filename = $url_path . '&guest';
46
+ $filename_guest_suffix = '&guest';
47
+ } else {
48
+ $filename = $url_path . '?guest';
49
+ $filename_guest_suffix = '?guest';
50
+ }
51
+
52
+ // Don't cache
53
+ if ( ! empty( $_COOKIE ) ) {
54
+ $wp_cookies = array( 'wordpressuser_', 'wordpresspass_', 'wordpress_sec_', 'wordpress_logged_in_' );
55
+
56
+ foreach ( $_COOKIE as $key => $value ) {
57
+ // Logged in!
58
+ if ( strpos( $key, 'wordpress_logged_in_' ) !== false ) {
59
+ $user_logged = true;
60
+ }
61
+ }
62
+
63
+ if ( $user_logged ) {
64
+ foreach ( $_COOKIE as $k => $v ) {
65
+ if ( strpos( $k, 'wordpress_logged_in_' ) !== false ) {
66
+ $nameuser = substr( $v, 0, strpos( $v, '|' ) );
67
+ if ( substr_count( $url_path, '?' ) > 0 ) {
68
+ $filename = $url_path . '&' . strtolower( $nameuser );
69
+ } else {
70
+ $filename = $url_path . '?' . strtolower( $nameuser );
71
+ }
72
+ }
73
+ }
74
+ }
75
+
76
+ if ( ! empty( $_COOKIE['breeze_commented_posts'] ) ) {
77
+ foreach ( $_COOKIE['breeze_commented_posts'] as $path ) {
78
+ if ( rtrim( $path, '/' ) === rtrim( $_SERVER['REQUEST_URI'], '/' ) ) {
79
+ // User commented on this post
80
+ return;
81
+ }
82
+ }
83
+ }
84
+ }
85
+
86
+ //check disable cache for page
87
+ $domain = ( ( ( ! empty( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] !== 'off' ) || $_SERVER['SERVER_PORT'] == 443 ) ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'];
88
+ //decode url with russian language
89
+ $current_url = $domain . rawurldecode( $_SERVER['REQUEST_URI'] );
90
+ $opts_config = $GLOBALS['breeze_config'];
91
+ $check_exclude = check_exclude_page( $opts_config, $current_url );
92
+
93
+ //load cache
94
+ if ( ! $check_exclude ) {
95
+ $devices = $opts_config['cache_options'];
96
+ $X1 = '';
97
+ // Detect devices
98
+ if ( $detect->isMobile() && ! $detect->isTablet() ) {
99
+ // The first X will be D for Desktop cache
100
+ // M for Mobile cache
101
+ // T for Tablet cache
102
+ if ( (int) $devices['breeze-mobile-cache'] == 1 ) {
103
+ $X1 = 'D';
104
+ $filename .= '_breeze_cache_desktop';
105
+ }
106
+ if ( (int) $devices['breeze-mobile-cache'] == 2 ) {
107
+ $X1 = 'M';
108
+ $filename .= '_breeze_cache_mobile';
109
+ }
110
+ } else {
111
+ if ( (int) $devices['breeze-desktop-cache'] == 1 ) {
112
+ $X1 = 'D';
113
+ $filename .= '_breeze_cache_desktop';
114
+ }
115
+ }
116
+
117
+ breeze_serve_cache( $filename, $url_path, $X1, $devices );
118
+ ob_start( 'breeze_cache' );
119
+ } else {
120
+ header( 'Cache-Control: no-cache' );
121
+ }
122
+
123
+ /**
124
+ * Cache output before it goes to the browser
125
+ *
126
+ * @param string $buffer
127
+ * @param int $flags
128
+ *
129
+ * @return string
130
+ * @since 1.0
131
+ */
132
+ function breeze_cache( $buffer, $flags ) {
133
+ // No cache for pages without 200 response status
134
+ if ( http_response_code() !== 200 ) {
135
+ return $buffer;
136
+ }
137
+
138
+ require_once 'Mobile-Detect-2.8.25/Mobile_Detect.php';
139
+ $detect = new \Cloudways\Breeze\Mobile_Detect\Mobile_Detect;
140
+ //not cache per administrator if option disable optimization for admin users clicked
141
+ if ( ! empty( $GLOBALS['breeze_config'] ) && (int) $GLOBALS['breeze_config']['disable_per_adminuser'] ) {
142
+ if ( function_exists( 'is_user_logged_in' ) && is_user_logged_in() ) {
143
+ $current_user = wp_get_current_user();
144
+ if ( in_array( 'administrator', $current_user->roles ) ) {
145
+ return $buffer;
146
+ }
147
+ }
148
+ }
149
+
150
+ if ( strlen( $buffer ) < 255 ) {
151
+ return $buffer;
152
+ }
153
+
154
+ // Don't cache search, 404, or password protected
155
+ if ( is_404() || is_search() || post_password_required() ) {
156
+ return $buffer;
157
+ }
158
+ global $wp_filesystem;
159
+ if ( empty( $wp_filesystem ) ) {
160
+ require_once( ABSPATH . '/wp-admin/includes/file.php' );
161
+ WP_Filesystem();
162
+ }
163
+ $url_path = breeze_get_url_path();
164
+
165
+ $blog_id_requested = isset( $GLOBALS['breeze_config']['blog_id'] ) ? $GLOBALS['breeze_config']['blog_id'] : 0;
166
+ $cache_base_path = breeze_get_cache_base_path( false, $blog_id_requested );
167
+
168
+ $path = $cache_base_path . md5( $url_path );
169
+
170
+ // Make sure we can read/write files and that proper folders exist
171
+ if ( ! wp_mkdir_p( $path ) ) {
172
+ // Can not cache!
173
+ return $buffer;
174
+ }
175
+ $path .= '/';
176
+
177
+ $modified_time = time(); // Make sure modified time is consistent
178
+
179
+ if ( preg_match( '#</html>#i', $buffer ) ) {
180
+ $buffer .= "\n<!-- Cache served by breeze CACHE - Last modified: " . gmdate( 'D, d M Y H:i:s', $modified_time ) . " GMT -->\n";
181
+ }
182
+ $headers = array(
183
+ array(
184
+ 'name' => 'Content-Length',
185
+ 'value' => strlen( $buffer ),
186
+ ),
187
+ array(
188
+ 'name' => 'Content-Type',
189
+ 'value' => 'text/html; charset=utf-8',
190
+ ),
191
+ array(
192
+ 'name' => 'Last-Modified',
193
+ 'value' => gmdate( 'D, d M Y H:i:s', $modified_time ) . ' GMT',
194
+ ),
195
+ );
196
+
197
+ if ( ! isset( $_SERVER['HTTP_X_VARNISH'] ) ) {
198
+ $headers = array_merge(
199
+ array(
200
+ array(
201
+ 'name' => 'Expires',
202
+ 'value' => 'Wed, 17 Aug 2005 00:00:00 GMT',
203
+ ),
204
+ array(
205
+ 'name' => 'Cache-Control',
206
+ 'value' => 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0',
207
+ ),
208
+ array(
209
+ 'name' => 'Pragma',
210
+ 'value' => 'no-cache',
211
+ ),
212
+ )
213
+ );
214
+ }
215
+
216
+ $data = serialize(
217
+ array(
218
+ 'body' => $buffer,
219
+ 'headers' => $headers,
220
+ )
221
+ );
222
+ //cache per users
223
+ if ( is_user_logged_in() ) {
224
+ $current_user = wp_get_current_user();
225
+ if ( $current_user->user_login ) {
226
+
227
+ if ( substr_count( $url_path, '?' ) > 0 ) {
228
+ $url_path .= '&' . $current_user->user_login;
229
+ } else {
230
+ $url_path .= '?' . $current_user->user_login;
231
+ }
232
+ #$url_path .= $current_user->user_login;
233
+ }
234
+ } else {
235
+ global $filename_guest_suffix;
236
+ $url_path .= $filename_guest_suffix;
237
+ }
238
+ $devices = $GLOBALS['breeze_config']['cache_options'];
239
+ // Detect devices
240
+ if ( $detect->isMobile() && ! $detect->isTablet() ) {
241
+ if ( $devices['breeze-mobile-cache'] == 1 ) {
242
+ $X1 = 'D';
243
+ $url_path .= '_breeze_cache_desktop';
244
+ }
245
+ if ( $devices['breeze-mobile-cache'] == 2 ) {
246
+ $X1 = 'M';
247
+ $url_path .= '_breeze_cache_mobile';
248
+ }
249
+ } else {
250
+ if ( $devices['breeze-desktop-cache'] == 1 ) {
251
+ $X1 = 'D';
252
+ $url_path .= '_breeze_cache_desktop';
253
+ }
254
+ }
255
+
256
+ if ( strpos( $url_path, '_breeze_cache_' ) !== false ) {
257
+ if ( ! empty( $GLOBALS['breeze_config']['cache_options']['breeze-gzip-compression'] ) && function_exists( 'gzencode' ) ) {
258
+ $wp_filesystem->put_contents( $path . md5( $url_path . '/index.gzip.html' ) . '.php', $data );
259
+ $wp_filesystem->touch( $path . md5( $url_path . '/index.gzip.html' ) . '.php', $modified_time );
260
+ } else {
261
+ $wp_filesystem->put_contents( $path . md5( $url_path . '/index.html' ) . '.php', $data );
262
+ $wp_filesystem->touch( $path . md5( $url_path . '/index.html' ) . '.php', $modified_time );
263
+ }
264
+ } else {
265
+ return $buffer;
266
+ }
267
+
268
+ //set cache provider header if not exists cache file
269
+ header( 'Cache-Provider:CLOUDWAYS-CACHE-' . $X1 . 'C' );
270
+
271
+ // Do not send this header in case we are behind a varnish proxy
272
+ if ( ! isset( $_SERVER['HTTP_X_VARNISH'] ) ) {
273
+ header( 'Cache-Control: no-cache' ); // Check back every time to see if re-download is necessary
274
+ }
275
+
276
+ header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s', $modified_time ) . ' GMT' );
277
+
278
+ if ( function_exists( 'ob_gzhandler' ) && ! empty( $GLOBALS['breeze_config']['cache_options']['breeze-gzip-compression'] ) ) {
279
+ $ini_output_compression = ini_get( 'zlib.output_compression' );
280
+ $array_values = array( '1', 'On', 'on' );
281
+ if ( in_array( $ini_output_compression, $array_values ) ) {
282
+ return $buffer;
283
+ } else {
284
+ return ob_gzhandler( $buffer, $flags );
285
+ }
286
+ } else {
287
+ return $buffer;
288
+ }
289
+ }
290
+
291
+ /**
292
+ * Get URL path for caching
293
+ *
294
+ * @return string
295
+ * @since 1.0
296
+ */
297
+ function breeze_get_url_path() {
298
+
299
+ $host = ( isset( $_SERVER['HTTP_HOST'] ) ) ? $_SERVER['HTTP_HOST'] : '';
300
+ $domain = ( ( ( ! empty( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] !== 'off' ) || ( ! empty( $_SERVER['SERVER_PORT'] ) && $_SERVER['SERVER_PORT'] == 443 ) ) ? 'https://' : 'http://' );
301
+
302
+ return $domain . rtrim( $host, '/' ) . $_SERVER['REQUEST_URI'];
303
+ }
304
+
305
+ /**
306
+ * Optionally serve cache and exit
307
+ *
308
+ * @since 1.0
309
+ */
310
+ function breeze_serve_cache( $filename, $url_path, $X1, $opts ) {
311
+ if ( strpos( $filename, '_breeze_cache_' ) === false ) {
312
+ return;
313
+ }
314
+
315
+ if ( function_exists( 'gzencode' ) && ! empty( $GLOBALS['breeze_config']['cache_options']['breeze-gzip-compression'] ) ) {
316
+ $file_name = md5( $filename . '/index.gzip.html' ) . '.php';
317
+ } else {
318
+ $file_name = md5( $filename . '/index.html' ) . '.php';
319
+ }
320
+
321
+ $blog_id_requested = isset( $GLOBALS['breeze_config']['blog_id'] ) ? $GLOBALS['breeze_config']['blog_id'] : 0;
322
+ $path = breeze_get_cache_base_path( false, $blog_id_requested ) . md5( $url_path ) . '/' . $file_name;
323
+
324
+ $modified_time = 0;
325
+ if ( file_exists( $path ) ) {
326
+ $modified_time = (int) @filemtime( $path );
327
+ }
328
+
329
+ if ( ! empty( $opts['breeze-browser-cache'] ) && ! empty( $modified_time ) && ! empty( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) && strtotime( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) === $modified_time ) {
330
+ header( $_SERVER['SERVER_PROTOCOL'] . ' 304 Not Modified', true, 304 );
331
+ exit;
332
+ }
333
+
334
+ if ( @file_exists( $path ) ) {
335
+
336
+ $cacheFile = file_get_contents( $path );
337
+
338
+ if ( $cacheFile != false ) {
339
+ $datas = unserialize( $cacheFile );
340
+ foreach ( $datas['headers'] as $data ) {
341
+ header( $data['name'] . ': ' . $data['value'] );
342
+ }
343
+ //set cache provider header
344
+ header( 'Cache-Provider:CLOUDWAYS-CACHE-' . $X1 . 'E' );
345
+
346
+ $client_support_gzip = true;
347
+
348
+ //check gzip request from client
349
+ if ( isset( $_SERVER['HTTP_ACCEPT_ENCODING'] ) && ( strpos( $_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip' ) === false || strpos( $_SERVER['HTTP_ACCEPT_ENCODING'], 'deflate' ) === false ) ) {
350
+ $client_support_gzip = false;
351
+ }
352
+
353
+ if ( $client_support_gzip && function_exists( 'gzdecode' ) && ! empty( $GLOBALS['breeze_config']['cache_options']['breeze-gzip-compression'] ) ) {
354
+ //if file is zip
355
+
356
+ $content = gzencode( $datas['body'], 9 );
357
+ header( 'Content-Encoding: gzip' );
358
+ header( 'cache-control: must-revalidate' );
359
+ header( 'Content-Length: ' . strlen( $content ) );
360
+ header( 'Vary: Accept-Encoding' );
361
+ echo $content;
362
+ } else {
363
+ //render page cache
364
+ echo $datas['body'];
365
+ }
366
+ exit;
367
+ }
368
+ }
369
+ }
370
+
371
+ function check_exclude_page( $opts_config, $current_url ) {
372
+ $is_feed = breeze_is_feed( $current_url );
373
+
374
+ if ( true === $is_feed ) {
375
+ return true;
376
+ }
377
+
378
+ //check disable cache for page
379
+ if ( ! empty( $opts_config['exclude_url'] ) ) {
380
+
381
+ $is_exclude = exec_breeze_check_for_exclude_values( $current_url, $opts_config['exclude_url'] );
382
+ if ( ! empty( $is_exclude ) ) {
383
+ return true;
384
+ }
385
+
386
+ foreach ( $opts_config['exclude_url'] as $v ) {
387
+ // Clear blank character
388
+ $v = trim( $v );
389
+ if ( preg_match( '/(\&?\/?\(\.?\*\)|\/\*|\*)$/', $v, $matches ) ) {
390
+ // End of rules is *, /*, [&][/](*) , [&][/](.*)
391
+ $pattent = substr( $v, 0, strpos( $v, $matches[0] ) );
392
+ if ( $v[0] == '/' ) {
393
+ // A path of exclude url with regex
394
+ if ( ( @preg_match( '@' . $pattent . '@', $current_url, $matches ) > 0 ) ) {
395
+ return true;
396
+ }
397
+ } else {
398
+ // Full exclude url with regex
399
+ if ( strpos( $current_url, $pattent ) !== false ) {
400
+ return true;
401
+ }
402
+ }
403
+ } else {
404
+ if ( $v[0] == '/' ) {
405
+ // A path of exclude
406
+ if ( ( @preg_match( '@' . $v . '@', $current_url, $matches ) > 0 ) ) {
407
+ return true;
408
+ }
409
+ } else { // Whole path
410
+ if ( $v == $current_url ) {
411
+ return true;
412
+ }
413
+ }
414
+ }
415
+ }
416
+ }
417
+
418
+ return false;
419
+ }
420
+
421
+
422
+ /**
423
+ * Used to check for regexp exclude pages
424
+ *
425
+ * @param string $needle
426
+ * @param array $haystack
427
+ *
428
+ * @return array
429
+ * @since 1.1.7
430
+ *
431
+ */
432
+ function exec_breeze_check_for_exclude_values( $needle = '', $haystack = array() ) {
433
+ if ( empty( $needle ) || empty( $haystack ) ) {
434
+ return array();
435
+ }
436
+ $needle = trim( $needle );
437
+ $is_string_in_array = array_filter(
438
+ $haystack,
439
+ function ( $var ) use ( $needle ) {
440
+ if ( exec_breeze_string_contains_exclude_regexp( $var ) ) {
441
+ return exec_breeze_file_match_pattern( $needle, $var );
442
+ } else {
443
+ return false;
444
+ }
445
+
446
+ }
447
+ );
448
+
449
+ return $is_string_in_array;
450
+ }
451
+
452
+
453
+ /**
454
+ * Function used to determine if the excluded URL contains regexp
455
+ *
456
+ * @param $file_url
457
+ * @param string $validate
458
+ *
459
+ * @return bool
460
+ */
461
+ function exec_breeze_string_contains_exclude_regexp( $file_url, $validate = '(.*)' ) {
462
+ if ( empty( $file_url ) ) {
463
+ return false;
464
+ }
465
+ if ( empty( $validate ) ) {
466
+ return false;
467
+ }
468
+
469
+ $valid = false;
470
+
471
+ if ( substr_count( $file_url, $validate ) !== 0 ) {
472
+ $valid = true; // 0 or false
473
+ }
474
+
475
+ return $valid;
476
+ }
477
+
478
+
479
+ /**
480
+ * Method will prepare the URLs escaped for preg_match
481
+ * Will return the file_url matches the pattern.
482
+ * empty array for false,
483
+ * aray with data for true.
484
+ *
485
+ * @param $file_url
486
+ * @param $pattern
487
+ *
488
+ * @return false|int
489
+ */
490
+ function exec_breeze_file_match_pattern( $file_url, $pattern ) {
491
+ $remove_pattern = str_replace( '(.*)', 'REG_EXP_ALL', $pattern );
492
+ $prepared_pattern = preg_quote( $remove_pattern, '/' );
493
+ $pattern = str_replace( 'REG_EXP_ALL', '(.*)', $prepared_pattern );
494
+ $result = preg_match( '/' . $pattern . '/', $file_url );
495
+
496
+ return $result;
497
+ }
498
+
inc/cache/purge-cache.php CHANGED
@@ -1,173 +1,175 @@
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
- if ( ! defined( 'ABSPATH' ) ) exit;
22
- class Breeze_PurgeCache {
23
-
24
- public function set_action() {
25
- add_action('pre_post_update', array($this, 'purge_post_on_update'), 10, 1);
26
- add_action('save_post', array($this, 'purge_post_on_update'), 10, 1);
27
- add_action('wp_trash_post', array($this, 'purge_post_on_update'), 10, 1);
28
- add_action('comment_post', array($this, 'purge_post_on_new_comment'), 10, 3);
29
- add_action('wp_set_comment_status', array($this, 'purge_post_on_comment_status_change'), 10, 2);
30
- add_action('set_comment_cookies', array($this, 'set_comment_cookie_exceptions'), 10, 2);
31
- }
32
-
33
- /**
34
- * When user posts a comment, set a cookie so we don't show them page cache
35
- *
36
- * @param WP_Comment $comment
37
- * @param WP_User $user
38
- * @since 1.3
39
- */
40
- public function set_comment_cookie_exceptions($comment, $user) {
41
- $config = breeze_get_option( 'basic_settings' );
42
- // File based caching only
43
- if (!empty($config['breeze-active'])) {
44
-
45
- $post_id = $comment->comment_post_ID;
46
-
47
- setcookie('breeze_commented_posts[' . $post_id . ']', parse_url(get_permalink($post_id), PHP_URL_PATH), ( time() + HOUR_IN_SECONDS * 24 * 30));
48
- }
49
- }
50
-
51
- // Automatically purge all file based page cache on post changes
52
- public function purge_post_on_update($post_id) {
53
- $post_type = get_post_type($post_id);
54
- if (( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) || 'revision' === $post_type) {
55
- return;
56
- } elseif (!current_user_can('edit_post', $post_id) && (!defined('DOING_CRON') || !DOING_CRON )) {
57
- return;
58
- }
59
-
60
- $config = breeze_get_option( 'basic_settings' );
61
-
62
- // File based caching only
63
- if (!empty($config['breeze-active'])) {
64
- self::breeze_cache_flush();
65
- }
66
- }
67
-
68
- public function purge_post_on_new_comment($comment_ID, $approved, $commentdata) {
69
- if (empty($approved)) {
70
- return;
71
- }
72
- $config = breeze_get_option( 'basic_settings' );
73
- // File based caching only
74
- if (!empty($config['breeze-active'])) {
75
- $post_id = $commentdata['comment_post_ID'];
76
-
77
- global $wp_filesystem;
78
-
79
- if ( empty( $wp_filesystem ) ) {
80
- require_once( ABSPATH . '/wp-admin/includes/file.php' );
81
- WP_Filesystem();
82
- }
83
-
84
- $url_path = get_permalink($post_id);
85
- if ( $wp_filesystem->exists( breeze_get_cache_base_path() . md5( $url_path ) ) ) {
86
- $wp_filesystem->rmdir( breeze_get_cache_base_path() . md5( $url_path ), true );
87
- }
88
- }
89
- }
90
-
91
- // if a comments status changes, purge it's parent posts cache
92
- public function purge_post_on_comment_status_change($comment_ID, $comment_status) {
93
- $config = breeze_get_option( 'basic_settings' );
94
-
95
- // File based caching only
96
- if (!empty($config['breeze-active'])) {
97
- $comment = get_comment($comment_ID);
98
- if(!empty($comment)){
99
- $post_id = $comment->comment_post_ID;
100
-
101
- global $wp_filesystem;
102
-
103
- WP_Filesystem();
104
-
105
- $url_path = get_permalink($post_id);
106
-
107
- if ( $wp_filesystem->exists( breeze_get_cache_base_path() . md5( $url_path ) ) ) {
108
- $wp_filesystem->rmdir( breeze_get_cache_base_path() . md5( $url_path ), true );
109
- }
110
- }
111
- }
112
- }
113
-
114
- //clean cache
115
- public static function breeze_cache_flush() {
116
- global $wp_filesystem;
117
-
118
- require_once( ABSPATH . 'wp-admin/includes/file.php');
119
-
120
- WP_Filesystem();
121
-
122
- $cache_path = breeze_get_cache_base_path( is_network_admin() );
123
- $wp_filesystem->rmdir( untrailingslashit( $cache_path ), true );
124
-
125
- if ( function_exists( 'wp_cache_flush' ) ) {
126
- wp_cache_flush();
127
- }
128
- }
129
-
130
- //delete file for clean up
131
-
132
- public function clean_up() {
133
-
134
- global $wp_filesystem;
135
- $file = untrailingslashit( WP_CONTENT_DIR ) . '/advanced-cache.php';
136
-
137
- $ret = true;
138
-
139
- if ( ! $wp_filesystem->delete( $file ) ) {
140
- $ret = false;
141
- }
142
-
143
- $folder = untrailingslashit( breeze_get_cache_base_path() );
144
-
145
- if ( ! $wp_filesystem->delete( $folder, true ) ) {
146
- $ret = false;
147
- }
148
-
149
- return $ret;
150
- }
151
-
152
- /**
153
- * Return an instance of the current class, create one if it doesn't exist
154
- * @since 1.0
155
- * @return object
156
- */
157
- public static function factory() {
158
-
159
- static $instance;
160
-
161
- if (!$instance) {
162
- $instance = new self();
163
- $instance->set_action();
164
- }
165
-
166
- return $instance;
167
- }
168
-
169
- }
170
- $settings = breeze_get_option( 'basic_settings' );
171
- if ( isset( $settings['breeze-active'] ) && $settings['breeze-active'] ) {
172
- Breeze_PurgeCache::factory();
173
- }
 
 
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
+ if ( ! defined( 'ABSPATH' ) ) {
22
+ exit;
23
+ }
24
+ class Breeze_PurgeCache {
25
+
26
+ public function set_action() {
27
+ add_action( 'pre_post_update', array( $this, 'purge_post_on_update' ), 10, 1 );
28
+ add_action( 'save_post', array( $this, 'purge_post_on_update' ), 10, 1 );
29
+ add_action( 'wp_trash_post', array( $this, 'purge_post_on_update' ), 10, 1 );
30
+ add_action( 'comment_post', array( $this, 'purge_post_on_new_comment' ), 10, 3 );
31
+ add_action( 'wp_set_comment_status', array( $this, 'purge_post_on_comment_status_change' ), 10, 2 );
32
+ add_action( 'set_comment_cookies', array( $this, 'set_comment_cookie_exceptions' ), 10, 2 );
33
+ }
34
+
35
+ /**
36
+ * When user posts a comment, set a cookie so we don't show them page cache
37
+ *
38
+ * @param WP_Comment $comment
39
+ * @param WP_User $user
40
+ * @since 1.3
41
+ */
42
+ public function set_comment_cookie_exceptions( $comment, $user ) {
43
+ $config = breeze_get_option( 'basic_settings' );
44
+ // File based caching only
45
+ if ( ! empty( $config['breeze-active'] ) ) {
46
+
47
+ $post_id = $comment->comment_post_ID;
48
+
49
+ setcookie( 'breeze_commented_posts[' . $post_id . ']', parse_url( get_permalink( $post_id ), PHP_URL_PATH ), ( time() + HOUR_IN_SECONDS * 24 * 30 ) );
50
+ }
51
+ }
52
+
53
+ // Automatically purge all file based page cache on post changes
54
+ public function purge_post_on_update( $post_id ) {
55
+ $post_type = get_post_type( $post_id );
56
+ if ( ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) || 'revision' === $post_type ) {
57
+ return;
58
+ } elseif ( ! current_user_can( 'edit_post', $post_id ) && ( ! defined( 'DOING_CRON' ) || ! DOING_CRON ) ) {
59
+ return;
60
+ }
61
+
62
+ $config = breeze_get_option( 'basic_settings' );
63
+
64
+ // File based caching only
65
+ if ( ! empty( $config['breeze-active'] ) ) {
66
+ self::breeze_cache_flush();
67
+ }
68
+ }
69
+
70
+ public function purge_post_on_new_comment( $comment_ID, $approved, $commentdata ) {
71
+ if ( empty( $approved ) ) {
72
+ return;
73
+ }
74
+ $config = breeze_get_option( 'basic_settings' );
75
+ // File based caching only
76
+ if ( ! empty( $config['breeze-active'] ) ) {
77
+ $post_id = $commentdata['comment_post_ID'];
78
+
79
+ global $wp_filesystem;
80
+
81
+ if ( empty( $wp_filesystem ) ) {
82
+ require_once( ABSPATH . '/wp-admin/includes/file.php' );
83
+ WP_Filesystem();
84
+ }
85
+
86
+ $url_path = get_permalink( $post_id );
87
+ if ( $wp_filesystem->exists( breeze_get_cache_base_path() . md5( $url_path ) ) ) {
88
+ $wp_filesystem->rmdir( breeze_get_cache_base_path() . md5( $url_path ), true );
89
+ }
90
+ }
91
+ }
92
+
93
+ // if a comments status changes, purge it's parent posts cache
94
+ public function purge_post_on_comment_status_change( $comment_ID, $comment_status ) {
95
+ $config = breeze_get_option( 'basic_settings' );
96
+
97
+ // File based caching only
98
+ if ( ! empty( $config['breeze-active'] ) ) {
99
+ $comment = get_comment( $comment_ID );
100
+ if ( ! empty( $comment ) ) {
101
+ $post_id = $comment->comment_post_ID;
102
+
103
+ global $wp_filesystem;
104
+
105
+ WP_Filesystem();
106
+
107
+ $url_path = get_permalink( $post_id );
108
+
109
+ if ( $wp_filesystem->exists( breeze_get_cache_base_path() . md5( $url_path ) ) ) {
110
+ $wp_filesystem->rmdir( breeze_get_cache_base_path() . md5( $url_path ), true );
111
+ }
112
+ }
113
+ }
114
+ }
115
+
116
+ //clean cache
117
+ public static function breeze_cache_flush() {
118
+ global $wp_filesystem;
119
+
120
+ require_once( ABSPATH . 'wp-admin/includes/file.php' );
121
+
122
+ WP_Filesystem();
123
+
124
+ $cache_path = breeze_get_cache_base_path( is_network_admin() );
125
+ $wp_filesystem->rmdir( untrailingslashit( $cache_path ), true );
126
+
127
+ if ( function_exists( 'wp_cache_flush' ) ) {
128
+ wp_cache_flush();
129
+ }
130
+ }
131
+
132
+ //delete file for clean up
133
+
134
+ public function clean_up() {
135
+
136
+ global $wp_filesystem;
137
+ $file = untrailingslashit( WP_CONTENT_DIR ) . '/advanced-cache.php';
138
+
139
+ $ret = true;
140
+
141
+ if ( ! $wp_filesystem->delete( $file ) ) {
142
+ $ret = false;
143
+ }
144
+
145
+ $folder = untrailingslashit( breeze_get_cache_base_path() );
146
+
147
+ if ( ! $wp_filesystem->delete( $folder, true ) ) {
148
+ $ret = false;
149
+ }
150
+
151
+ return $ret;
152
+ }
153
+
154
+ /**
155
+ * Return an instance of the current class, create one if it doesn't exist
156
+ * @since 1.0
157
+ * @return object
158
+ */
159
+ public static function factory() {
160
+
161
+ static $instance;
162
+
163
+ if ( ! $instance ) {
164
+ $instance = new self();
165
+ $instance->set_action();
166
+ }
167
+
168
+ return $instance;
169
+ }
170
+
171
+ }
172
+ $settings = breeze_get_option( 'basic_settings' );
173
+ if ( isset( $settings['breeze-active'] ) && $settings['breeze-active'] ) {
174
+ Breeze_PurgeCache::factory();
175
+ }
inc/cache/purge-per-time.php CHANGED
@@ -1,121 +1,120 @@
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_PurgeCacheTime {
24
- protected $timettl = false;
25
- protected $normalcache = 0;
26
- protected $varnishcache = 0;
27
- public function __construct($settings = null)
28
- {
29
- if ( isset( $settings['breeze-ttl'] ) ) {
30
- $this->timettl = $settings['breeze-ttl'];
31
- }
32
-
33
- if ( isset( $settings['breeze-active'] ) ) {
34
- $this->normalcache = (int) $settings['breeze-active'];
35
- }
36
-
37
- if ( isset( $settings['breeze-varnish-purge'] ) ) {
38
- $this->varnishcache = (int) $settings['breeze-varnish-purge'];
39
- }
40
-
41
- add_action( 'breeze_purge_cache', array( $this, 'schedule_varnish' ) );
42
- add_action( 'init', array( $this, 'schedule_events' ) );
43
- add_filter( 'cron_schedules', array( $this, 'filter_cron_schedules' ) );
44
-
45
- }
46
- // * Unschedule events
47
- public function unschedule_events() {
48
- $timestamp = wp_next_scheduled( 'breeze_purge_cache' );
49
-
50
- wp_unschedule_event( $timestamp, 'breeze_purge_cache' );
51
- }
52
- // set up schedule_events
53
- public function schedule_events() {
54
-
55
- $timestamp = wp_next_scheduled( 'breeze_purge_cache' );
56
-
57
- // Expire cache never
58
- if ( isset( $this->timettl ) && (int)$this->timettl === 0 ) {
59
- wp_unschedule_event( $timestamp, 'breeze_purge_cache' );
60
- return;
61
- }
62
-
63
- if ( ! $timestamp ) {
64
- wp_schedule_event( time(), 'breeze_varnish_time', 'breeze_purge_cache' );
65
- }
66
- }
67
-
68
- /**
69
- * Add custom cron schedule
70
- */
71
- public function filter_cron_schedules( $schedules ) {
72
- if ( !empty( $this->timettl ) && is_numeric($this->timettl) && (int)$this->timettl > 0 ) {
73
- $interval = $this->timettl * 60;
74
- } else {
75
- $interval = '86400'; // One day
76
- }
77
-
78
- $schedules['breeze_varnish_time'] = array(
79
- 'interval' => apply_filters( 'breeze_varnish_purge_interval', $interval ),
80
- 'display' => esc_html__( 'Cloudways Varnish Purge Interval', 'breeze' ),
81
- );
82
-
83
- return $schedules;
84
- }
85
-
86
- //execute purge varnish after time life
87
- public function schedule_varnish(){
88
- // Purge varnish cache
89
- if($this->varnishcache){
90
- do_action('breeze_clear_varnish');
91
- }
92
-
93
- // Purge normal cache
94
- if($this->normalcache){
95
- Breeze_PurgeCache::breeze_cache_flush();
96
- Breeze_MinificationCache::clear_minification();
97
- }
98
-
99
- }
100
-
101
- public static function factory() {
102
- static $instance;
103
- if ( ! $instance ) {
104
- $instance = new self();
105
- }
106
- return $instance;
107
- }
108
- }
109
-
110
- $basic = breeze_get_option( 'basic_settings' );
111
- $varnish = breeze_get_option( 'varnish_cache' );
112
- //Enabled auto purge the varnish caching by time life
113
- $params = array(
114
- 'breeze-active' => (isset($basic['breeze-active'])?(int)$basic['breeze-active']:0),
115
- 'breeze-ttl' => (isset($basic['breeze-ttl'])?(int)$basic['breeze-ttl']:0),
116
- 'breeze-varnish-purge' => (isset($varnish['auto-purge-varnish'])?(int)$varnish['auto-purge-varnish']:0),
117
- );
118
-
119
- if($params['breeze-active'] || $params['breeze-varnish-purge']){
120
- $purgeTime = new Breeze_PurgeCacheTime($params);
121
- }
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_PurgeCacheTime {
24
+ protected $timettl = false;
25
+ protected $normalcache = 0;
26
+ protected $varnishcache = 0;
27
+ public function __construct( $settings = null ) {
28
+ if ( isset( $settings['breeze-ttl'] ) ) {
29
+ $this->timettl = $settings['breeze-ttl'];
30
+ }
31
+
32
+ if ( isset( $settings['breeze-active'] ) ) {
33
+ $this->normalcache = (int) $settings['breeze-active'];
34
+ }
35
+
36
+ if ( isset( $settings['breeze-varnish-purge'] ) ) {
37
+ $this->varnishcache = (int) $settings['breeze-varnish-purge'];
38
+ }
39
+
40
+ add_action( 'breeze_purge_cache', array( $this, 'schedule_varnish' ) );
41
+ add_action( 'init', array( $this, 'schedule_events' ) );
42
+ add_filter( 'cron_schedules', array( $this, 'filter_cron_schedules' ) );
43
+
44
+ }
45
+ // * Unschedule events
46
+ public function unschedule_events() {
47
+ $timestamp = wp_next_scheduled( 'breeze_purge_cache' );
48
+
49
+ wp_unschedule_event( $timestamp, 'breeze_purge_cache' );
50
+ }
51
+ // set up schedule_events
52
+ public function schedule_events() {
53
+
54
+ $timestamp = wp_next_scheduled( 'breeze_purge_cache' );
55
+
56
+ // Expire cache never
57
+ if ( isset( $this->timettl ) && (int) $this->timettl === 0 ) {
58
+ wp_unschedule_event( $timestamp, 'breeze_purge_cache' );
59
+ return;
60
+ }
61
+
62
+ if ( ! $timestamp ) {
63
+ wp_schedule_event( time(), 'breeze_varnish_time', 'breeze_purge_cache' );
64
+ }
65
+ }
66
+
67
+ /**
68
+ * Add custom cron schedule
69
+ */
70
+ public function filter_cron_schedules( $schedules ) {
71
+ if ( ! empty( $this->timettl ) && is_numeric( $this->timettl ) && (int) $this->timettl > 0 ) {
72
+ $interval = $this->timettl * 60;
73
+ } else {
74
+ $interval = '86400'; // One day
75
+ }
76
+
77
+ $schedules['breeze_varnish_time'] = array(
78
+ 'interval' => apply_filters( 'breeze_varnish_purge_interval', $interval ),
79
+ 'display' => esc_html__( 'Cloudways Varnish Purge Interval', 'breeze' ),
80
+ );
81
+
82
+ return $schedules;
83
+ }
84
+
85
+ //execute purge varnish after time life
86
+ public function schedule_varnish() {
87
+ // Purge varnish cache
88
+ if ( $this->varnishcache ) {
89
+ do_action( 'breeze_clear_varnish' );
90
+ }
91
+
92
+ // Purge normal cache
93
+ if ( $this->normalcache ) {
94
+ Breeze_PurgeCache::breeze_cache_flush();
95
+ Breeze_MinificationCache::clear_minification();
96
+ }
97
+
98
+ }
99
+
100
+ public static function factory() {
101
+ static $instance;
102
+ if ( ! $instance ) {
103
+ $instance = new self();
104
+ }
105
+ return $instance;
106
+ }
107
+ }
108
+
109
+ $basic = breeze_get_option( 'basic_settings' );
110
+ $varnish = breeze_get_option( 'varnish_cache' );
111
+ //Enabled auto purge the varnish caching by time life
112
+ $params = array(
113
+ 'breeze-active' => ( isset( $basic['breeze-active'] ) ? (int) $basic['breeze-active'] : 0 ),
114
+ 'breeze-ttl' => ( isset( $basic['breeze-ttl'] ) ? (int) $basic['breeze-ttl'] : 0 ),
115
+ 'breeze-varnish-purge' => ( isset( $varnish['auto-purge-varnish'] ) ? (int) $varnish['auto-purge-varnish'] : 0 ),
116
+ );
117
+
118
+ if ( $params['breeze-active'] || $params['breeze-varnish-purge'] ) {
119
+ $purgeTime = new Breeze_PurgeCacheTime( $params );
120
+ }
 
inc/cache/purge-varnish.php CHANGED
@@ -22,9 +22,9 @@ 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
@@ -93,7 +93,6 @@ class Breeze_PurgeVarnish {
93
  $this->purge_cache( $url );
94
  }
95
  }
96
-
97
  } else {
98
  $homepage = home_url() . '/?breeze';
99
  if ( isset( $_REQUEST['breeze_action'] ) && $_REQUEST['breeze_action'] == 'breeze_settings' ) {
@@ -288,7 +287,7 @@ class Breeze_PurgeVarnish {
288
  $listofurls,
289
  get_post_type_archive_link( get_post_type( $postId ) ),
290
  get_post_type_archive_feed_link( get_post_type( $postId ) )
291
- // Need to add in JSON?
292
  );
293
  }
294
  // Feeds
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
93
  $this->purge_cache( $url );
94
  }
95
  }
 
96
  } else {
97
  $homepage = home_url() . '/?breeze';
98
  if ( isset( $_REQUEST['breeze_action'] ) && $_REQUEST['breeze_action'] == 'breeze_settings' ) {
287
  $listofurls,
288
  get_post_type_archive_link( get_post_type( $postId ) ),
289
  get_post_type_archive_feed_link( get_post_type( $postId ) )
290
+ // Need to add in JSON?
291
  );
292
  }
293
  // Feeds
inc/cdn-integration/breeze-cdn-integration.php CHANGED
@@ -1,62 +1,62 @@
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_CDN_Integration{
24
-
25
- public function __construct(){
26
- add_action('template_redirect', array($this,'handle_rewrite_cdn'));
27
- }
28
-
29
- /**
30
- * Execute rewrite cdn
31
- */
32
- public function handle_rewrite_cdn(){
33
- $cdn_integration = breeze_get_option( 'cdn_integration' );
34
-
35
- if(empty($cdn_integration) || empty($cdn_integration['cdn-active'])){
36
- return;
37
- }
38
-
39
- if($cdn_integration['cdn-url'] == ''){
40
- return;
41
- }
42
-
43
- if(get_option('home') == $cdn_integration['cdn-url']){
44
- return;
45
- }
46
-
47
- if ( isset( $_GET['action'] ) && 'edit' === $_GET['action'] && isset( $_GET['job_id'] ) && ! empty( $_GET['job_id'] ) ) {
48
- return;
49
- }
50
-
51
- $rewrite = new Breeze_CDN_Rewrite($cdn_integration);
52
-
53
- //rewrite CDN Url to html raw
54
- // ob_start(array(&$rewrite,'rewrite'));
55
- add_filter('breeze_cdn_content_return',array(&$rewrite,'rewrite'));
56
-
57
- }
58
-
59
- public static function instance(){
60
- new self();
61
- }
62
- }
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_CDN_Integration {
24
+
25
+ public function __construct() {
26
+ add_action( 'template_redirect', array( $this, 'handle_rewrite_cdn' ) );
27
+ }
28
+
29
+ /**
30
+ * Execute rewrite cdn
31
+ */
32
+ public function handle_rewrite_cdn() {
33
+ $cdn_integration = breeze_get_option( 'cdn_integration' );
34
+
35
+ if ( empty( $cdn_integration ) || empty( $cdn_integration['cdn-active'] ) ) {
36
+ return;
37
+ }
38
+
39
+ if ( $cdn_integration['cdn-url'] == '' ) {
40
+ return;
41
+ }
42
+
43
+ if ( get_option( 'home' ) == $cdn_integration['cdn-url'] ) {
44
+ return;
45
+ }
46
+
47
+ if ( isset( $_GET['action'] ) && 'edit' === $_GET['action'] && isset( $_GET['job_id'] ) && ! empty( $_GET['job_id'] ) ) {
48
+ return;
49
+ }
50
+
51
+ $rewrite = new Breeze_CDN_Rewrite( $cdn_integration );
52
+
53
+ //rewrite CDN Url to html raw
54
+ // ob_start(array(&$rewrite,'rewrite'));
55
+ add_filter( 'breeze_cdn_content_return', array( &$rewrite, 'rewrite' ) );
56
+
57
+ }
58
+
59
+ public static function instance() {
60
+ new self();
61
+ }
62
+ }
inc/cdn-integration/breeze-cdn-rewrite.php CHANGED
@@ -1,145 +1,145 @@
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_CDN_Rewrite {
24
- private $blog_url = null;
25
- private $cdn_url = null;
26
- private $dirs = array();
27
- private $excludes = array();
28
- private $relative = false;
29
-
30
- public function __construct(&$option){
31
- //storage option
32
- $this->blog_url = get_option('home');
33
- $this->cdn_url = $option['cdn-url'];
34
- $this->dirs = $option['cdn-content'];
35
- $this->excludes = $option['cdn-exclude-content'];
36
- $this->relative = $option['cdn-relative-path'];
37
-
38
- $this->hardcoded_exceptions_to_ignore();
39
- }
40
-
41
- /**
42
- * Handles extra exceptions which need to be excluded
43
- * and instead use local URL instead of CDN.
44
- *
45
- * @since 1.1.3
46
- */
47
- private function hardcoded_exceptions_to_ignore() {
48
- if ( ! array( $this->excludes ) || empty( $this->excludes ) ) {
49
- $this->excludes = array();
50
- }
51
- $this->excludes [] = 'download_file';
52
- // Allow users to use filter and add exceptions from CDN url.
53
- $this->excludes = apply_filters( 'breeze_cdn_exclude_paths', $this->excludes );
54
- }
55
-
56
- /*
57
- * Replace cdn on html raw
58
- */
59
- public function rewrite($content){
60
-
61
- $blog_url = quotemeta($this->blog_url);
62
-
63
- // get dir scope in regex format
64
- $dirs = $this->get_dir_scope();
65
-
66
- // regex rule start
67
- $regex_rule = '#(?<=[(\"\'])';
68
-
69
- // create blog url without http or https
70
- $parseurl = parse_url($this->blog_url);
71
- $scheme = 'http:';
72
- if(!empty($parseurl['scheme'])){
73
- $scheme = $parseurl['scheme'].':';
74
- }
75
- $blog_url_short = str_replace($scheme, '',$this->blog_url);
76
-
77
- // check if relative paths
78
- if ($this->relative) {
79
- $regex_rule .= '(?:'.$blog_url.'|'.$blog_url_short.')?';
80
- } else {
81
- $regex_rule .= '('.$blog_url.'|'.$blog_url_short.')';
82
- }
83
-
84
- // regex rule end
85
- $regex_rule .= '/(?:((?:'.$dirs.')[^\"\')]+)|([^/\"\']+\.[^/\"\')]+))(?=[\"\')])#';
86
-
87
- // call the cdn rewriter callback
88
- $new_content = preg_replace_callback($regex_rule, array(&$this, 'replace_cdn_url'), $content);
89
-
90
- return $new_content;
91
- }
92
-
93
- /**
94
- * get directory scope
95
- */
96
-
97
- protected function get_dir_scope() {
98
- // default
99
- if (empty($this->dirs) || count($this->dirs) < 1) {
100
- return 'wp\-content|wp\-includes';
101
- }
102
-
103
- return implode('|', array_map('quotemeta', array_map('trim', $this->dirs)));
104
- }
105
-
106
- /*
107
- * Replace cdn url to root url
108
- */
109
- protected function replace_cdn_url($match){
110
- //return file type or directories excluded
111
- if($this->excludes_check($match[0])){
112
- return $match[0];
113
- }
114
-
115
- $parseUrl = parse_url($this->blog_url);
116
- $scheme = 'http://';
117
- if(isset($parseUrl['scheme'])){
118
- $scheme = $parseUrl['scheme'].'://';
119
- }
120
- $host = $parseUrl['host'];
121
- //get domain
122
- $domain = '//'.$host;
123
-
124
- // check if not a relative path
125
- if (!$this->relative || strstr($match[0], $this->blog_url)) {
126
- $domain = $scheme.$host;
127
- }
128
-
129
- return str_replace($domain, $this->cdn_url, $match[0]);
130
-
131
- }
132
- /*
133
- * Check excludes assets
134
- */
135
- protected function excludes_check($dir){
136
- if(!empty($this->excludes)){
137
- foreach ($this->excludes as $exclude){
138
- if(stristr($dir, $exclude) != false){
139
- return true;
140
- }
141
- }
142
- }
143
- return false;
144
- }
145
- }
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_CDN_Rewrite {
24
+ private $blog_url = null;
25
+ private $cdn_url = null;
26
+ private $dirs = array();
27
+ private $excludes = array();
28
+ private $relative = false;
29
+
30
+ public function __construct( &$option ) {
31
+ //storage option
32
+ $this->blog_url = get_option( 'home' );
33
+ $this->cdn_url = $option['cdn-url'];
34
+ $this->dirs = $option['cdn-content'];
35
+ $this->excludes = $option['cdn-exclude-content'];
36
+ $this->relative = $option['cdn-relative-path'];
37
+
38
+ $this->hardcoded_exceptions_to_ignore();
39
+ }
40
+
41
+ /**
42
+ * Handles extra exceptions which need to be excluded
43
+ * and instead use local URL instead of CDN.
44
+ *
45
+ * @since 1.1.3
46
+ */
47
+ private function hardcoded_exceptions_to_ignore() {
48
+ if ( ! array( $this->excludes ) || empty( $this->excludes ) ) {
49
+ $this->excludes = array();
50
+ }
51
+ $this->excludes [] = 'download_file';
52
+ // Allow users to use filter and add exceptions from CDN url.
53
+ $this->excludes = apply_filters( 'breeze_cdn_exclude_paths', $this->excludes );
54
+ }
55
+
56
+ /*
57
+ * Replace cdn on html raw
58
+ */
59
+ public function rewrite( $content ) {
60
+
61
+ $blog_url = quotemeta( $this->blog_url );
62
+
63
+ // get dir scope in regex format
64
+ $dirs = $this->get_dir_scope();
65
+
66
+ // regex rule start
67
+ $regex_rule = '#(?<=[(\"\'])';
68
+
69
+ // create blog url without http or https
70
+ $parseurl = parse_url( $this->blog_url );
71
+ $scheme = 'http:';
72
+ if ( ! empty( $parseurl['scheme'] ) ) {
73
+ $scheme = $parseurl['scheme'] . ':';
74
+ }
75
+ $blog_url_short = str_replace( $scheme, '', $this->blog_url );
76
+
77
+ // check if relative paths
78
+ if ( $this->relative ) {
79
+ $regex_rule .= '(?:' . $blog_url . '|' . $blog_url_short . ')?';
80
+ } else {
81
+ $regex_rule .= '(' . $blog_url . '|' . $blog_url_short . ')';
82
+ }
83
+
84
+ // regex rule end
85
+ $regex_rule .= '/(?:((?:' . $dirs . ')[^\"\')]+)|([^/\"\']+\.[^/\"\')]+))(?=[\"\')])#';
86
+
87
+ // call the cdn rewriter callback
88
+ $new_content = preg_replace_callback( $regex_rule, array( &$this, 'replace_cdn_url' ), $content );
89
+
90
+ return $new_content;
91
+ }
92
+
93
+ /**
94
+ * get directory scope
95
+ */
96
+
97
+ protected function get_dir_scope() {
98
+ // default
99
+ if ( empty( $this->dirs ) || count( $this->dirs ) < 1 ) {
100
+ return 'wp\-content|wp\-includes';
101
+ }
102
+
103
+ return implode( '|', array_map( 'quotemeta', array_map( 'trim', $this->dirs ) ) );
104
+ }
105
+
106
+ /*
107
+ * Replace cdn url to root url
108
+ */
109
+ protected function replace_cdn_url( $match ) {
110
+ //return file type or directories excluded
111
+ if ( $this->excludes_check( $match[0] ) ) {
112
+ return $match[0];
113
+ }
114
+
115
+ $parseUrl = parse_url( $this->blog_url );
116
+ $scheme = 'http://';
117
+ if ( isset( $parseUrl['scheme'] ) ) {
118
+ $scheme = $parseUrl['scheme'] . '://';
119
+ }
120
+ $host = $parseUrl['host'];
121
+ //get domain
122
+ $domain = '//' . $host;
123
+
124
+ // check if not a relative path
125
+ if ( ! $this->relative || strstr( $match[0], $this->blog_url ) ) {
126
+ $domain = $scheme . $host;
127
+ }
128
+
129
+ return str_replace( $domain, $this->cdn_url, $match[0] );
130
+
131
+ }
132
+ /*
133
+ * Check excludes assets
134
+ */
135
+ protected function excludes_check( $dir ) {
136
+ if ( ! empty( $this->excludes ) ) {
137
+ foreach ( $this->excludes as $exclude ) {
138
+ if ( stristr( $dir, $exclude ) != false ) {
139
+ return true;
140
+ }
141
+ }
142
+ }
143
+ return false;
144
+ }
145
+ }
inc/class-breeze-woocommerce-product-cache.php ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ header( 'Status: 403 Forbidden' );
4
+ header( 'HTTP/1.1 403 Forbidden' );
5
+ exit;
6
+ }
7
+
8
+ class Breeze_Woocommerce_Product_Cache {
9
+ function __construct() {
10
+ // When a new order is placed.
11
+ add_action( 'woocommerce_checkout_order_processed', array( &$this, 'recreate_cache_for_products' ), 10, 3 );
12
+ }
13
+
14
+ /**
15
+ * When a new order is placed we must re-create the cache for the order
16
+ * products to refresh the stock value.
17
+ *
18
+ * @param int $order_id The order ID.
19
+ *
20
+ * @since 1.1.10
21
+ */
22
+ public function recreate_cache_for_products( $order_id, $posted_data, $order ) {
23
+
24
+ if ( ! empty( $order_id ) ) {
25
+
26
+ // Checks if the Varnish server is ON.
27
+ $do_varnish_purge = is_varnish_cache_started();
28
+
29
+ // fetch the order data.
30
+ $order_id = absint( $order_id );
31
+ $order = new WC_Order( $order_id );
32
+ // Fetch the order products.
33
+ $items = $order->get_items();
34
+
35
+ if ( ! empty( $items ) ) {
36
+ foreach ( $items as $item_id => $item_product ) {
37
+ $product_id = $item_product->get_product_id();
38
+
39
+ if ( ! empty( $product_id ) ) {
40
+ $url_path = get_permalink( $product_id );
41
+
42
+ // Clear Varnish server cache for this URL.
43
+ breeze_varnish_purge_cache( $url_path, $do_varnish_purge );
44
+ }
45
+ }
46
+ }
47
+ }
48
+
49
+ }
50
+ }
51
+
52
+
53
+ add_action(
54
+ 'init',
55
+ function () {
56
+ if ( class_exists( 'WooCommerce' ) ) {
57
+ new Breeze_Woocommerce_Product_Cache();
58
+ }
59
+ }
60
+ );
61
+
62
+
inc/class-exclude-pages-by-shortcode.php CHANGED
@@ -20,7 +20,6 @@ class Exclude_Pages_By_Shortcode {
20
  public function post_check_content_on_save( $post_id = 0, $post = null, $update = false ) {
21
  $content = trim( $post->post_content );
22
 
23
-
24
  if ( 'page' !== $post->post_type ) {
25
  return;
26
  }
@@ -41,23 +40,24 @@ class Exclude_Pages_By_Shortcode {
41
  $data = $output_shortcodes[1];
42
  $data = array_unique( $data );
43
 
44
-
45
  foreach ( $shortcode_list as $shortcode ) {
46
- $result = array_filter( $data, function ( $item ) use ( $shortcode ) {
47
- $shortcode = str_replace( '(.*)', '', $shortcode );
48
- if ( stripos( $item, $shortcode ) !== false ) {
49
- return true;
 
 
 
 
 
50
  }
51
-
52
- return false;
53
- } );
54
 
55
  if ( ! empty( $result ) ) {
56
  $found = true;
57
  break;
58
  }
59
  }
60
-
61
  }
62
 
63
  if ( true === $found ) {
@@ -117,4 +117,4 @@ class Exclude_Pages_By_Shortcode {
117
  }
118
  }
119
 
120
- new Exclude_Pages_By_Shortcode();
20
  public function post_check_content_on_save( $post_id = 0, $post = null, $update = false ) {
21
  $content = trim( $post->post_content );
22
 
 
23
  if ( 'page' !== $post->post_type ) {
24
  return;
25
  }
40
  $data = $output_shortcodes[1];
41
  $data = array_unique( $data );
42
 
 
43
  foreach ( $shortcode_list as $shortcode ) {
44
+ $result = array_filter(
45
+ $data,
46
+ function ( $item ) use ( $shortcode ) {
47
+ $shortcode = str_replace( '(.*)', '', $shortcode );
48
+ if ( stripos( $item, $shortcode ) !== false ) {
49
+ return true;
50
+ }
51
+
52
+ return false;
53
  }
54
+ );
 
 
55
 
56
  if ( ! empty( $result ) ) {
57
  $found = true;
58
  break;
59
  }
60
  }
 
61
  }
62
 
63
  if ( true === $found ) {
117
  }
118
  }
119
 
120
+ new Exclude_Pages_By_Shortcode();
inc/functions.php CHANGED
@@ -36,17 +36,15 @@ function breeze_get_cache_base_path( $is_network = false, $blog_id_requested = 0
36
  if ( ! $is_network && is_multisite() ) {
37
 
38
  if ( empty( $blog_id_requested ) ) {
39
-
40
  global $blog_id;
41
  $path = rtrim( WP_CONTENT_DIR, '/\\' ) . '/cache/breeze/';
42
  if ( ! empty( $blog_id ) ) {
43
  $path .= abs( intval( $blog_id ) ) . DIRECTORY_SEPARATOR;
44
  }
45
  } else {
46
- $path = rtrim( WP_CONTENT_DIR, '/\\' ) . '/cache/breeze/';
47
  $path .= abs( intval( $blog_id_requested ) ) . DIRECTORY_SEPARATOR;
48
  }
49
-
50
  } else {
51
  $path = rtrim( WP_CONTENT_DIR, '/\\' ) . '/cache/breeze/';
52
  }
@@ -125,4 +123,4 @@ function breeze_is_feed( $url ) {
125
 
126
  return false;
127
 
128
- }
36
  if ( ! $is_network && is_multisite() ) {
37
 
38
  if ( empty( $blog_id_requested ) ) {
 
39
  global $blog_id;
40
  $path = rtrim( WP_CONTENT_DIR, '/\\' ) . '/cache/breeze/';
41
  if ( ! empty( $blog_id ) ) {
42
  $path .= abs( intval( $blog_id ) ) . DIRECTORY_SEPARATOR;
43
  }
44
  } else {
45
+ $path = rtrim( WP_CONTENT_DIR, '/\\' ) . '/cache/breeze/';
46
  $path .= abs( intval( $blog_id_requested ) ) . DIRECTORY_SEPARATOR;
47
  }
 
48
  } else {
49
  $path = rtrim( WP_CONTENT_DIR, '/\\' ) . '/cache/breeze/';
50
  }
123
 
124
  return false;
125
 
126
+ }
inc/helpers.php CHANGED
@@ -255,7 +255,7 @@ function breeze_check_for_exclude_values( $needle = '', $haystack = array() ) {
255
  $is_string_in_array = array_filter(
256
  $haystack,
257
  function ( $var ) use ( $needle ) {
258
- #return false;
259
  if ( breeze_string_contains_exclude_regexp( $var ) ) {
260
  return breeze_file_match_pattern( $needle, $var );
261
  } else {
@@ -631,4 +631,122 @@ function multisite_blog_id_config() {
631
  if ( ! empty( $blog_id ) ) {
632
 
633
  }
634
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
255
  $is_string_in_array = array_filter(
256
  $haystack,
257
  function ( $var ) use ( $needle ) {
258
+
259
  if ( breeze_string_contains_exclude_regexp( $var ) ) {
260
  return breeze_file_match_pattern( $needle, $var );
261
  } else {
631
  if ( ! empty( $blog_id ) ) {
632
 
633
  }
634
+ }
635
+
636
+ /**
637
+ * Purges the cache for a given URL.
638
+ * Varnish cache and local cache.
639
+ *
640
+ * @param string $url The url for which to purge the cache.
641
+ * @param false $purge_varnish If the check was already done for Varnish server On/OFF set to true.
642
+ * @param bool $check_varnish If the check for Varnish was not done, set to true to check Varnish server status inside the function.
643
+ *
644
+ * @since 1.1.10
645
+ */
646
+ function breeze_varnish_purge_cache( $url = '', $purge_varnish = false, $check_varnish = true ) {
647
+ global $wp_filesystem;
648
+
649
+ // Making sure the filesystem is loaded.
650
+ if ( empty( $wp_filesystem ) ) {
651
+ require_once( ABSPATH . '/wp-admin/includes/file.php' );
652
+ WP_Filesystem();
653
+ }
654
+
655
+ // Clear the local cache using the product URL.
656
+ if ( ! empty( $url ) && $wp_filesystem->exists( breeze_get_cache_base_path() . md5( $url ) ) ) {
657
+ $wp_filesystem->rmdir( breeze_get_cache_base_path() . md5( $url ), true );
658
+ }
659
+
660
+ if ( false === $purge_varnish && true === $check_varnish ) {
661
+ // Checks if the Varnish server is ON.
662
+ $do_varnish_purge = is_varnish_cache_started();
663
+
664
+ if ( false === $do_varnish_purge ) {
665
+ return;
666
+ }
667
+ }
668
+
669
+ if ( false === $purge_varnish && false === $check_varnish ) {
670
+ return;
671
+ }
672
+
673
+ $parse_url = parse_url( $url );
674
+ $pregex = '';
675
+ // Default method is URLPURGE to purge only one object, this method is specific to cloudways configuration
676
+ $purge_method = 'URLPURGE';
677
+ // Use PURGE method when purging all site
678
+ if ( isset( $parse_url['query'] ) && ( 'breeze' === strtolower( $parse_url['query'] ) ) ) {
679
+ // The regex is not needed as cloudways configuration purge all the cache of the domain when a PURGE is done
680
+ $pregex = '.*';
681
+ $purge_method = 'PURGE';
682
+ }
683
+ // Determine the path
684
+ $url_path = '';
685
+ if ( isset( $parse_url['path'] ) ) {
686
+ $url_path = $parse_url['path'];
687
+ }
688
+ // Determine the schema
689
+ $schema = 'http://';
690
+ if ( isset( $parse_url['scheme'] ) ) {
691
+ $schema = $parse_url['scheme'] . '://';
692
+ }
693
+ // Determine the host
694
+ $host = $parse_url['host'];
695
+ $config = breeze_get_option( 'varnish_cache' );
696
+ $varnish_host = isset( $config['breeze-varnish-server-ip'] ) ? $config['breeze-varnish-server-ip'] : '127.0.0.1';
697
+ $purgeme = $varnish_host . $url_path . $pregex;
698
+ if ( ! empty( $parse_url['query'] ) && 'breeze' !== strtolower( $parse_url['query'] ) ) {
699
+ $purgeme .= '?' . $parse_url['query'];
700
+ }
701
+ $request_args = array(
702
+ 'method' => $purge_method,
703
+ 'headers' => array(
704
+ 'Host' => $host,
705
+ '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',
706
+ ),
707
+ 'sslverify' => false,
708
+ );
709
+ $response = wp_remote_request( $schema . $purgeme, $request_args );
710
+ if ( is_wp_error( $response ) || 200 !== (int) $response['response']['code'] ) {
711
+ if ( 'https://' === $schema ) {
712
+ $schema = 'http://';
713
+ } else {
714
+ $schema = 'https://';
715
+ }
716
+ wp_remote_request( $schema . $purgeme, $request_args );
717
+ }
718
+ }
719
+
720
+ /**
721
+ * Will ignore the files added into $minified_already array so that these files will not be minified twice.
722
+ *
723
+ * @param string $script_path local script path.
724
+ *
725
+ * @return bool
726
+ * @since 1.1.9
727
+ */
728
+ function breeze_libraries_already_minified( $script_path = '' ) {
729
+ if ( empty( $script_path ) ) {
730
+ return false;
731
+ }
732
+
733
+ $minified_already = array(
734
+ 'woocommerce-bookings/dist/frontend.js',
735
+ );
736
+
737
+ $library = explode( '/plugins/', $script_path );
738
+
739
+ if ( empty( $library ) || ! isset( $library[1] ) ) {
740
+ return false;
741
+ }
742
+
743
+ $library_path = $library[1];
744
+
745
+ if ( in_array( $library_path, $minified_already ) ) {
746
+ return true;
747
+ }
748
+
749
+ return false;
750
+
751
+ }
752
+ add_filter( 'breeze_js_ignore_minify', 'breeze_libraries_already_minified' );
inc/minification/breeze-js-deferred-loading.php CHANGED
@@ -23,6 +23,14 @@ class Breeze_Js_Deferred_Loading extends Breeze_MinificationBase {
23
  */
24
  private $defer_js = array();
25
 
 
 
 
 
 
 
 
 
26
  /**
27
  * Will hold the JS Scripts found in the header
28
  * @var array
@@ -83,7 +91,7 @@ class Breeze_Js_Deferred_Loading extends Breeze_MinificationBase {
83
  'jd.gallery.transitions.js',
84
  'swfobject.embedSWF(',
85
  'tiny_mce.js',
86
- 'tinyMCEPreInit.go'
87
  );
88
 
89
  private $domovelast = array(
@@ -168,6 +176,9 @@ class Breeze_Js_Deferred_Loading extends Breeze_MinificationBase {
168
  // comments
169
  $this->content = $this->hide_comments( $this->content );
170
 
 
 
 
171
  //Get script files
172
  $split_content = explode( '</head>', $this->content, 2 );
173
  $this->fetch_javascript( $split_content[0] );
@@ -198,6 +209,17 @@ class Breeze_Js_Deferred_Loading extends Breeze_MinificationBase {
198
  * @access private
199
  */
200
  private function fetch_javascript( $content = '', $head = true ) {
 
 
 
 
 
 
 
 
 
 
 
201
  if ( preg_match_all( '#<script.*</script>#Usmi', $content, $matches ) ) {
202
  foreach ( $matches[0] as $tag ) {
203
  // only consider aggregation whitelisted in should_aggregate-function
@@ -230,8 +252,24 @@ class Breeze_Js_Deferred_Loading extends Breeze_MinificationBase {
230
  //We can merge it
231
  if ( true === $head ) {
232
  // If this file will be move to footer
233
- if ( in_array( $url, $this->move_to_footer_js ) ) {
234
- $this->move_to_footer[ $url ] = $path;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
235
  } else {
236
  $this->head_scripts[ $url ] = $path;
237
  }
@@ -311,6 +349,20 @@ class Breeze_Js_Deferred_Loading extends Breeze_MinificationBase {
311
  * @access public
312
  */
313
  public function getcontent() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
314
 
315
  // Load inline JS to html
316
  if ( ! empty( $this->head_scripts ) ) {
@@ -320,13 +372,20 @@ class Breeze_Js_Deferred_Loading extends Breeze_MinificationBase {
320
 
321
  foreach ( $this->head_scripts as $js_url => $js_path ) {
322
  $defer = '';
323
- if ( gettype( $js_url ) == 'string' && in_array( $js_url, $this->defer_js ) ) {
 
 
 
 
 
 
 
324
  $defer = 'defer ';
325
  }
326
 
327
  $js_head[] = "<script type='application/javascript' {$defer}src='{$js_url}'></script>\n";
328
  }
329
- $js_replacement = '';
330
  $js_replacement .= implode( '', $js_head );
331
  $this->inject_in_html( $js_replacement, $replaceTag );
332
  }
@@ -337,18 +396,23 @@ class Breeze_Js_Deferred_Loading extends Breeze_MinificationBase {
337
 
338
  foreach ( $this->footer_scripts as $js_url => $js_path ) {
339
  $defer = '';
340
- if ( gettype( $js_url ) == 'string' && in_array( $js_url, $this->defer_js ) ) {
 
 
 
 
 
 
341
  $defer = 'defer ';
342
  }
343
 
344
  $js_footer[] = "<script type='application/javascript' {$defer}src='{$js_url}'></script>\n";
345
  }
346
- $js_replacement = '';
347
  $js_replacement .= implode( '', $js_footer );
348
  $this->inject_in_html( $js_replacement, $replaceTag );
349
  }
350
 
351
-
352
  // restore comments
353
  $this->content = $this->restore_comments( $this->content );
354
 
@@ -477,4 +541,41 @@ class Breeze_Js_Deferred_Loading extends Breeze_MinificationBase {
477
  return false;
478
  }
479
  }
480
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  */
24
  private $defer_js = array();
25
 
26
+ /**
27
+ * CDN domain.
28
+ *
29
+ * @since 1.1.8
30
+ * @access private
31
+ */
32
+ protected $cdn_url = '';
33
+
34
  /**
35
  * Will hold the JS Scripts found in the header
36
  * @var array
91
  'jd.gallery.transitions.js',
92
  'swfobject.embedSWF(',
93
  'tiny_mce.js',
94
+ 'tinyMCEPreInit.go',
95
  );
96
 
97
  private $domovelast = array(
176
  // comments
177
  $this->content = $this->hide_comments( $this->content );
178
 
179
+ // get cdn url
180
+ $this->cdn_url = $options['cdn_url'];
181
+
182
  //Get script files
183
  $split_content = explode( '</head>', $this->content, 2 );
184
  $this->fetch_javascript( $split_content[0] );
209
  * @access private
210
  */
211
  private function fetch_javascript( $content = '', $head = true ) {
212
+ $cdn_array_move_to_footer = array();
213
+
214
+ if ( ! empty( $this->move_to_footer_js ) ) {
215
+ foreach ( $this->move_to_footer_js as $index => $key ) {
216
+ $cdn_array_move_to_footer[ $this->url_replace_cdn( $index ) ] = $this->url_replace_cdn( $key );
217
+ $index = ltrim( $index, 'https:' );
218
+ $key = ltrim( $key, 'https:' );
219
+ $cdn_array_move_to_footer[ $this->url_replace_cdn( $index ) ] = $this->url_replace_cdn( $key );
220
+ }
221
+ }
222
+
223
  if ( preg_match_all( '#<script.*</script>#Usmi', $content, $matches ) ) {
224
  foreach ( $matches[0] as $tag ) {
225
  // only consider aggregation whitelisted in should_aggregate-function
252
  //We can merge it
253
  if ( true === $head ) {
254
  // If this file will be move to footer
255
+ $compare_url = ltrim( $url, 'https:' );
256
+ $cdn_url = $this->url_replace_cdn( $url );
257
+ $cdn_url_trim = ltrim( $cdn_url, 'https:' );
258
+
259
+ if (
260
+ ( in_array( $compare_url, $this->move_to_footer_js ) ||
261
+ in_array( $url, $this->move_to_footer_js ) ||
262
+ in_array( $cdn_url, $this->move_to_footer_js ) ||
263
+ in_array( $cdn_url_trim, $this->move_to_footer_js )
264
+ ) ||
265
+ (
266
+ in_array( $compare_url, $cdn_array_move_to_footer ) ||
267
+ in_array( $url, $cdn_array_move_to_footer ) ||
268
+ in_array( $cdn_url, $cdn_array_move_to_footer ) ||
269
+ in_array( $cdn_url_trim, $cdn_array_move_to_footer )
270
+ )
271
+ ) {
272
+ $this->footer_scripts[ $url ] = $path;
273
  } else {
274
  $this->head_scripts[ $url ] = $path;
275
  }
349
  * @access public
350
  */
351
  public function getcontent() {
352
+ if ( ! empty( $this->cdn_url ) ) {
353
+ foreach ( $this->defer_js as $index => $key ) {
354
+ $this->defer_js[ $this->url_replace_cdn( $index ) ] = $this->url_replace_cdn( $key );
355
+ $index = ltrim( $index, 'https:' );
356
+ $key = ltrim( $key, 'https:' );
357
+ $this->defer_js[ $this->url_replace_cdn( $index ) ] = $this->url_replace_cdn( $key );
358
+ }
359
+ } else {
360
+ foreach ( $this->defer_js as $index => $key ) {
361
+ $index = ltrim( $index, 'https:' );
362
+ $key = ltrim( $key, 'https:' );
363
+ $this->defer_js[ $index ] = $key;
364
+ }
365
+ }
366
 
367
  // Load inline JS to html
368
  if ( ! empty( $this->head_scripts ) ) {
372
 
373
  foreach ( $this->head_scripts as $js_url => $js_path ) {
374
  $defer = '';
375
+
376
+ if ( ! empty( $this->cdn_url ) ) {
377
+ $js_url = $this->url_replace_cdn( $js_url );
378
+ }
379
+
380
+ $js_url_trim = ltrim( $js_url, 'https:' );
381
+
382
+ if ( gettype( $js_url ) == 'string' && ( in_array( $js_url, $this->defer_js ) || in_array( $js_url_trim, $this->defer_js ) ) ) {
383
  $defer = 'defer ';
384
  }
385
 
386
  $js_head[] = "<script type='application/javascript' {$defer}src='{$js_url}'></script>\n";
387
  }
388
+ $js_replacement = '';
389
  $js_replacement .= implode( '', $js_head );
390
  $this->inject_in_html( $js_replacement, $replaceTag );
391
  }
396
 
397
  foreach ( $this->footer_scripts as $js_url => $js_path ) {
398
  $defer = '';
399
+ if ( ! empty( $this->cdn_url ) ) {
400
+ $js_url = $this->url_replace_cdn( $js_url );
401
+ }
402
+
403
+ $js_url_trim = ltrim( $js_url, 'https:' );
404
+
405
+ if ( gettype( $js_url ) == 'string' && ( in_array( $js_url, $this->defer_js ) || in_array( $js_url_trim, $this->defer_js ) ) ) {
406
  $defer = 'defer ';
407
  }
408
 
409
  $js_footer[] = "<script type='application/javascript' {$defer}src='{$js_url}'></script>\n";
410
  }
411
+ $js_replacement = '';
412
  $js_replacement .= implode( '', $js_footer );
413
  $this->inject_in_html( $js_replacement, $replaceTag );
414
  }
415
 
 
416
  // restore comments
417
  $this->content = $this->restore_comments( $this->content );
418
 
541
  return false;
542
  }
543
  }
544
+
545
+ /**
546
+ * Change the URL from local domain to CDN domain.
547
+ *
548
+ * @param string $url the given URL
549
+ *
550
+ * @return mixed|void
551
+ */
552
+ protected function url_replace_cdn( $url ) {
553
+ $cdn_url = apply_filters( 'breeze_filter_base_cdnurl', $this->cdn_url );
554
+ if ( ! empty( $cdn_url ) ) {
555
+ // secondly prepend domain-less absolute URL's
556
+ if ( ( substr( $url, 0, 1 ) === '/' ) && ( substr( $url, 1, 1 ) !== '/' ) ) {
557
+ $url = rtrim( $cdn_url, '/' ) . $url;
558
+ } else {
559
+ // get WordPress base URL
560
+ $WPSiteBreakdown = parse_url( breeze_WP_SITE_URL );
561
+ $WPBaseUrl = $WPSiteBreakdown['scheme'] . '://' . $WPSiteBreakdown['host'];
562
+ if ( ! empty( $WPSiteBreakdown['port'] ) ) {
563
+ $WPBaseUrl .= ':' . $WPSiteBreakdown['port'];
564
+ }
565
+ // three: replace full url's with scheme
566
+ $tmp_url = str_replace( $WPBaseUrl, rtrim( $cdn_url, '/' ), $url );
567
+ if ( $tmp_url === $url ) {
568
+ // last attempt; replace scheme-less URL's
569
+ $url = str_replace( preg_replace( '/https?:/', '', $WPBaseUrl ), rtrim( $cdn_url, '/' ), $url );
570
+ } else {
571
+ $url = $tmp_url;
572
+ }
573
+ }
574
+ }
575
+
576
+ // allow API filter to take alter after CDN replacement
577
+ $url = apply_filters( 'breeze_filter_base_replace_cdn', $url );
578
+
579
+ return $url;
580
+ }
581
+ }
inc/minification/breeze-minification-base.php CHANGED
@@ -1,394 +1,387 @@
1
- <?php
2
- /*
3
- * Based on some work of autoptimize plugin
4
- */
5
- if ( ! defined( 'ABSPATH' ) ) {
6
- exit;
7
- } // Exit if accessed directly
8
-
9
- abstract class Breeze_MinificationBase {
10
- protected $content = '';
11
- protected $tagWarning = false;
12
-
13
- public function __construct( $content ) {
14
- $this->content = $content;
15
- }
16
-
17
- //Reads the page and collects tags
18
- abstract public function read( $justhead );
19
-
20
- //Joins and optimizes collected things
21
- abstract public function minify();
22
-
23
- //Caches the things
24
- abstract public function cache();
25
-
26
- //Returns the content
27
- abstract public function getcontent();
28
-
29
- //Converts an URL to a full path
30
- protected function getpath( $url ) {
31
- $url = apply_filters( 'breeze_filter_cssjs_alter_url', $url );
32
-
33
- if ( strpos( $url, '%' ) !== false ) {
34
- $url = urldecode( $url );
35
- }
36
-
37
- // normalize
38
- if ( strpos( $url, '//' ) === 0 ) {
39
- if ( is_ssl() ) {
40
- $url = "https:" . $url;
41
- } else {
42
- $url = "http:" . $url;
43
- }
44
- } else if ( ( strpos( $url, '//' ) === false ) && ( strpos( $url, parse_url( breeze_WP_SITE_URL, PHP_URL_HOST ) ) === false ) ) {
45
- $url = breeze_WP_SITE_URL . $url;
46
- }
47
-
48
- // first check; hostname wp site should be hostname of url
49
- $thisHost = @parse_url( $url, PHP_URL_HOST );
50
- if ( $thisHost !== parse_url( breeze_WP_SITE_URL, PHP_URL_HOST ) ) {
51
- /*
52
- * first try to get all domains from WPML (if available)
53
- * then explicitely declare $this->cdn_url as OK as well
54
- * then apply own filter autoptimize_filter_cssjs_multidomain takes an array of hostnames
55
- * each item in that array will be considered part of the same WP multisite installation
56
- */
57
- $multidomains = array();
58
-
59
- $multidomainsWPML = apply_filters( 'wpml_setting', array(), 'language_domains' );
60
- if ( ! empty( $multidomainsWPML ) ) {
61
- $multidomains = array_map( array( $this, "ao_getDomain" ), $multidomainsWPML );
62
- }
63
-
64
- if ( ! empty( $this->cdn_url ) ) {
65
- $multidomains[] = parse_url( $this->cdn_url, PHP_URL_HOST );
66
- }
67
-
68
- $multidomains = apply_filters( 'breeze_filter_cssjs_multidomain', $multidomains );
69
-
70
- if ( ! empty( $multidomains ) ) {
71
- if ( in_array( $thisHost, $multidomains ) ) {
72
- $url = str_replace( $thisHost, parse_url( breeze_WP_SITE_URL, PHP_URL_HOST ), $url );
73
- } else {
74
- return false;
75
- }
76
- } else {
77
- return false;
78
- }
79
- }
80
-
81
- // try to remove "wp root url" from url while not minding http<>https
82
- $tmp_ao_root = preg_replace( '/https?/', '', breeze_WP_ROOT_URL );
83
- $tmp_url = preg_replace( '/https?/', '', $url );
84
- $path = str_replace( $tmp_ao_root, '', $tmp_url );
85
-
86
- // final check; if path starts with :// or //, this is not a URL in the WP context and we have to assume we can't aggregate
87
- if ( preg_match( '#^:?//#', $path ) ) {
88
- /** External script/css (adsense, etc) */
89
- return false;
90
- }
91
-
92
- $path = str_replace( '//', '/', BREEZE_ROOT_DIR . $path );
93
-
94
- return $path;
95
- }
96
-
97
- // needed for WPML-filter
98
- protected function ao_getDomain( $in ) {
99
- // make sure the url starts with something vaguely resembling a protocol
100
- if ( ( strpos( $in, "http" ) !== 0 ) && ( strpos( $in, "//" ) !== 0 ) ) {
101
- $in = "http://" . $in;
102
- }
103
-
104
- // do the actual parse_url
105
- $out = parse_url( $in, PHP_URL_HOST );
106
-
107
- // fallback if parse_url does not understand the url is in fact a url
108
- if ( empty( $out ) ) {
109
- $out = $in;
110
- }
111
-
112
- return $out;
113
- }
114
-
115
-
116
- // logger
117
- protected function ao_logger( $logmsg, $appendHTML = true ) {
118
- if ( $appendHTML ) {
119
- $logmsg = "<!--noptimize--><!-- " . $logmsg . " --><!--/noptimize-->";
120
- $this->content .= $logmsg;
121
- } else {
122
- error_log( "Error: " . $logmsg );
123
- }
124
- }
125
-
126
- // hide everything between noptimize-comment tags
127
- protected function hide_noptimize( $noptimize_in ) {
128
- if ( preg_match( '/<!--\s?noptimize\s?-->/', $noptimize_in ) ) {
129
- $noptimize_out = preg_replace_callback(
130
- '#<!--\s?noptimize\s?-->.*?<!--\s?/\s?noptimize\s?-->#is',
131
-
132
- function ( $matches ) {
133
- return "%%NOPTIMIZE" . breeze_HASH . "%%" . base64_encode( $matches[0] ) . "%%NOPTIMIZE%%";
134
- },
135
- $noptimize_in
136
- );
137
- } else {
138
- $noptimize_out = $noptimize_in;
139
- }
140
-
141
- return $noptimize_out;
142
- }
143
-
144
- // unhide noptimize-tags
145
- protected function restore_noptimize( $noptimize_in ) {
146
- if ( strpos( $noptimize_in, '%%NOPTIMIZE%%' ) !== false ) {
147
- $noptimize_out = preg_replace_callback(
148
- '#%%NOPTIMIZE' . breeze_HASH . '%%(.*?)%%NOPTIMIZE%%#is',
149
-
150
- function ( $matches ) {
151
- return base64_decode( $matches[1] );
152
- },
153
- $noptimize_in
154
- );
155
- } else {
156
- $noptimize_out = $noptimize_in;
157
- }
158
-
159
- return $noptimize_out;
160
- }
161
-
162
- protected function hide_iehacks( $iehacks_in ) {
163
- if ( strpos( $iehacks_in, '<!--[if' ) !== false ) {
164
- $iehacks_out = preg_replace_callback(
165
- '#<!--\[if.*?\[endif\]-->#is',
166
-
167
- function ( $matches ) {
168
- return "%%IEHACK" . breeze_HASH . "%%" . base64_encode( $matches[0] ) . "%%IEHACK%%";
169
- },
170
-
171
- $iehacks_in
172
- );
173
- } else {
174
- $iehacks_out = $iehacks_in;
175
- }
176
-
177
- return $iehacks_out;
178
- }
179
-
180
- protected function restore_iehacks( $iehacks_in ) {
181
- if ( strpos( $iehacks_in, '%%IEHACK%%' ) !== false ) {
182
- $iehacks_out = preg_replace_callback(
183
- '#%%IEHACK' . breeze_HASH . '%%(.*?)%%IEHACK%%#is',
184
-
185
- function ( $matches ) {
186
- return base64_decode( $matches[1] );
187
- },
188
- $iehacks_in
189
- );
190
- } else {
191
- $iehacks_out = $iehacks_in;
192
- }
193
-
194
- return $iehacks_out;
195
- }
196
-
197
- protected function hide_comments( $comments_in ) {
198
- if ( strpos( $comments_in, '<!--' ) !== false ) {
199
- $comments_out = preg_replace_callback(
200
- '#<!--.*?-->#is',
201
-
202
- function ( $matches ) {
203
- return "%%COMMENTS" . breeze_HASH . "%%" . base64_encode( $matches[0] ) . "%%COMMENTS%%";
204
- },
205
- $comments_in
206
- );
207
- } else {
208
- $comments_out = $comments_in;
209
- }
210
-
211
- return $comments_out;
212
- }
213
-
214
- protected function restore_comments( $comments_in ) {
215
- if ( strpos( $comments_in, '%%COMMENTS%%' ) !== false ) {
216
- $comments_out = preg_replace_callback(
217
- '#%%COMMENTS' . breeze_HASH . '%%(.*?)%%COMMENTS%%#is',
218
-
219
- function ( $matches ) {
220
- return base64_decode( $matches[1] );
221
- },
222
- $comments_in
223
- );
224
- } else {
225
- $comments_out = $comments_in;
226
- }
227
-
228
- return $comments_out;
229
- }
230
-
231
- protected function url_replace_cdn( $url ) {
232
- $cdn_url = apply_filters( 'breeze_filter_base_cdnurl', $this->cdn_url );
233
- if ( ! empty( $cdn_url ) ) {
234
- // secondly prepend domain-less absolute URL's
235
- if ( ( substr( $url, 0, 1 ) === '/' ) && ( substr( $url, 1, 1 ) !== '/' ) ) {
236
- $url = rtrim( $cdn_url, '/' ) . $url;
237
- } else {
238
- // get wordpress base URL
239
- $WPSiteBreakdown = parse_url( breeze_WP_SITE_URL );
240
- $WPBaseUrl = $WPSiteBreakdown['scheme'] . '://' . $WPSiteBreakdown['host'];
241
- if ( ! empty( $WPSiteBreakdown['port'] ) ) {
242
- $WPBaseUrl .= ":" . $WPSiteBreakdown['port'];
243
- }
244
- // three: replace full url's with scheme
245
- $tmp_url = str_replace( $WPBaseUrl, rtrim( $cdn_url, '/' ), $url );
246
- if ( $tmp_url === $url ) {
247
- // last attempt; replace scheme-less URL's
248
- $url = str_replace( preg_replace( '/https?:/', '', $WPBaseUrl ), rtrim( $cdn_url, '/' ), $url );
249
- } else {
250
- $url = $tmp_url;
251
- }
252
- }
253
- }
254
-
255
- // allow API filter to take alter after CDN replacement
256
- $url = apply_filters( 'breeze_filter_base_replace_cdn', $url );
257
-
258
- return $url;
259
- }
260
-
261
- protected function inject_in_html( $payload, $replaceTag ) {
262
- if ( strpos( $this->content, $replaceTag[0] ) !== false ) {
263
- if ( $replaceTag[1] === "after" ) {
264
- $replaceBlock = $replaceTag[0] . $payload;
265
- } else if ( $replaceTag[1] === "replace" ) {
266
- $replaceBlock = $payload;
267
- } else {
268
- $replaceBlock = $payload . $replaceTag[0];
269
- }
270
- $this->content = substr_replace( $this->content, $replaceBlock, strpos( $this->content, $replaceTag[0] ), strlen( $replaceTag[0] ) );
271
- } else {
272
- $this->content .= $payload;
273
- if ( ! $this->tagWarning ) {
274
- $this->content .= "<!--noptimize--><!-- breeze found a problem with the HTML in your Theme, tag " . $replaceTag[0] . " missing --><!--/noptimize-->";
275
- $this->tagWarning = true;
276
- }
277
- }
278
- }
279
-
280
- protected function isremovable( $tag, $removables ) {
281
- foreach ( $removables as $match ) {
282
- if ( strpos( $tag, $match ) !== false ) {
283
- return true;
284
- }
285
- }
286
-
287
- return false;
288
- }
289
-
290
- // inject already minified code in optimized JS/CSS
291
- protected function inject_minified( $in ) {
292
- if ( strpos( $in, '%%INJECTLATER%%' ) !== false ) {
293
- $out = preg_replace_callback(
294
- '#%%INJECTLATER' . breeze_HASH . '%%(.*?)%%INJECTLATER%%#is',
295
-
296
- function ( $matches ) {
297
- $filepath = base64_decode( strtok( $matches[1], "|" ) );
298
- $filecontent = file_get_contents( $filepath );
299
- if(empty(trim($filecontent))){
300
- return '';
301
- }
302
-
303
- // remove BOM
304
- $filecontent = preg_replace( "#\x{EF}\x{BB}\x{BF}#", "", $filecontent );
305
-
306
- // remove comments and blank lines
307
- if ( substr( $filepath, - 3, 3 ) === ".js" ) {
308
- $filecontent = preg_replace( "#^\s*\/\/.*$#Um", "", $filecontent );
309
- }
310
-
311
- $filecontent = preg_replace( "#^\s*\/\*[^!].*\*\/\s?#Us", "", $filecontent );
312
- $filecontent = preg_replace( "#(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+#", "\n", $filecontent );
313
-
314
- // specific stuff for JS-files
315
- if ( substr( $filepath, - 3, 3 ) === ".js" ) {
316
- if ( ( substr( $filecontent, - 1, 1 ) !== ";" ) && ( substr( $filecontent, - 1, 1 ) !== "}" ) ) {
317
- $filecontent .= ";";
318
- }
319
-
320
- if ( get_option( "breeze_js_trycatch" ) === "on" ) {
321
- $filecontent = "try{" . $filecontent . "}catch(e){}";
322
- }
323
- } else if ( ( substr( $filepath, - 4, 4 ) === ".css" ) ) {
324
- $filecontent = Breeze_MinificationStyles::fixurls( $filepath, $filecontent );
325
- }
326
-
327
- // return
328
- return "\n" . $filecontent;
329
- },
330
- $in
331
- );
332
- } else {
333
- $out = $in;
334
- }
335
-
336
- return $out;
337
- }
338
-
339
- /**
340
- * Handles clear cache for the situation where cache files do not exist.
341
- * @since 1.1.3
342
- */
343
- protected function clear_cache_data() {
344
- //delete minify
345
- Breeze_MinificationCache::clear_minification();
346
- //clear normal cache
347
- Breeze_PurgeCache::breeze_cache_flush();
348
-
349
- //Breeze_PurgeCache::factory();
350
- //clear varnish cache
351
- $varnish_cache = new Breeze_PurgeVarnish();
352
-
353
- $is_network = ( is_network_admin() || ( ! empty( $_POST['is_network'] ) && 'true' === $_POST['is_network'] ) );
354
-
355
- if ( is_multisite() && $is_network ) {
356
- $sites = get_sites();
357
- foreach ( $sites as $site ) {
358
- switch_to_blog( $site->blog_id );
359
- $homepage = home_url() . '/?breeze';
360
- $varnish_cache->purge_cache( $homepage );
361
- restore_current_blog();
362
- }
363
- } else {
364
- $homepage = home_url() . '/?breeze';
365
- $varnish_cache->purge_cache( $homepage );
366
- }
367
- }
368
-
369
- /**
370
- * Helps to check if the cache file actually exists.
371
- *
372
- * @param string $file_path Full file path.
373
- *
374
- * @return bool
375
- * @since 1.1.3
376
- */
377
- protected function is_cache_file_present( $file_path = '' ) {
378
- if ( file_exists( $file_path ) ) {
379
- return true;
380
- }
381
-
382
- return false;
383
- }
384
-
385
- public function get_cache_file_url( $type = 'css' ) {
386
- $cache_dir = BREEZE_MINIFICATION_CACHE . breeze_current_user_type() . ( ! empty( $type ) ? $type . '/' : '' );
387
- if ( is_multisite() ) {
388
- $blog_id = get_current_blog_id();
389
- $cache_dir = BREEZE_MINIFICATION_CACHE . $blog_id . '/' . breeze_current_user_type() . ( ! empty( $type ) ? $type . '/' : '' );
390
- }
391
-
392
- return $cache_dir;
393
- }
394
- }
1
+ <?php
2
+ /*
3
+ * Based on some work of autoptimize plugin
4
+ */
5
+ if ( ! defined( 'ABSPATH' ) ) {
6
+ exit;
7
+ } // Exit if accessed directly
8
+
9
+ abstract class Breeze_MinificationBase {
10
+ protected $content = '';
11
+ protected $tagWarning = false;
12
+ protected $cdn_url = '';
13
+
14
+ public function __construct( $content ) {
15
+ $this->content = $content;
16
+ }
17
+
18
+ //Reads the page and collects tags
19
+ abstract public function read( $justhead );
20
+
21
+ //Joins and optimizes collected things
22
+ abstract public function minify();
23
+
24
+ //Caches the things
25
+ abstract public function cache();
26
+
27
+ //Returns the content
28
+ abstract public function getcontent();
29
+
30
+ //Converts an URL to a full path
31
+ protected function getpath( $url ) {
32
+ $url = apply_filters( 'breeze_filter_cssjs_alter_url', $url );
33
+
34
+ if ( strpos( $url, '%' ) !== false ) {
35
+ $url = urldecode( $url );
36
+ }
37
+
38
+ // normalize
39
+ if ( strpos( $url, '//' ) === 0 ) {
40
+ if ( is_ssl() ) {
41
+ $url = 'https:' . $url;
42
+ } else {
43
+ $url = 'http:' . $url;
44
+ }
45
+ } elseif ( ( strpos( $url, '//' ) === false ) && ( strpos( $url, parse_url( breeze_WP_SITE_URL, PHP_URL_HOST ) ) === false ) ) {
46
+ $url = breeze_WP_SITE_URL . $url;
47
+ }
48
+
49
+ // first check; hostname wp site should be hostname of url
50
+ $thisHost = @parse_url( $url, PHP_URL_HOST );
51
+ if ( $thisHost !== parse_url( breeze_WP_SITE_URL, PHP_URL_HOST ) ) {
52
+ /*
53
+ * first try to get all domains from WPML (if available)
54
+ * then explicitely declare $this->cdn_url as OK as well
55
+ * then apply own filter autoptimize_filter_cssjs_multidomain takes an array of hostnames
56
+ * each item in that array will be considered part of the same WP multisite installation
57
+ */
58
+ $multidomains = array();
59
+
60
+ $multidomainsWPML = apply_filters( 'wpml_setting', array(), 'language_domains' );
61
+ if ( ! empty( $multidomainsWPML ) ) {
62
+ $multidomains = array_map( array( $this, 'ao_getDomain' ), $multidomainsWPML );
63
+ }
64
+
65
+ if ( ! empty( $this->cdn_url ) ) {
66
+ $multidomains[] = parse_url( $this->cdn_url, PHP_URL_HOST );
67
+ }
68
+
69
+ $multidomains = apply_filters( 'breeze_filter_cssjs_multidomain', $multidomains );
70
+
71
+ if ( ! empty( $multidomains ) ) {
72
+ if ( in_array( $thisHost, $multidomains ) ) {
73
+ $url = str_replace( $thisHost, parse_url( breeze_WP_SITE_URL, PHP_URL_HOST ), $url );
74
+ } else {
75
+ return false;
76
+ }
77
+ } else {
78
+ return false;
79
+ }
80
+ }
81
+
82
+ // try to remove "wp root url" from url while not minding http<>https
83
+ $tmp_ao_root = preg_replace( '/https?/', '', breeze_WP_ROOT_URL );
84
+ $tmp_url = preg_replace( '/https?/', '', $url );
85
+ $path = str_replace( $tmp_ao_root, '', $tmp_url );
86
+
87
+ // final check; if path starts with :// or //, this is not a URL in the WP context and we have to assume we can't aggregate
88
+ if ( preg_match( '#^:?//#', $path ) ) {
89
+ /** External script/css (adsense, etc) */
90
+ return false;
91
+ }
92
+
93
+ $path = str_replace( '//', '/', BREEZE_ROOT_DIR . $path );
94
+
95
+ return $path;
96
+ }
97
+
98
+ // needed for WPML-filter
99
+ protected function ao_getDomain( $in ) {
100
+ // make sure the url starts with something vaguely resembling a protocol
101
+ if ( ( strpos( $in, 'http' ) !== 0 ) && ( strpos( $in, '//' ) !== 0 ) ) {
102
+ $in = 'http://' . $in;
103
+ }
104
+
105
+ // do the actual parse_url
106
+ $out = parse_url( $in, PHP_URL_HOST );
107
+
108
+ // fallback if parse_url does not understand the url is in fact a url
109
+ if ( empty( $out ) ) {
110
+ $out = $in;
111
+ }
112
+
113
+ return $out;
114
+ }
115
+
116
+
117
+ // logger
118
+ protected function ao_logger( $logmsg, $appendHTML = true ) {
119
+ if ( $appendHTML ) {
120
+ $logmsg = '<!--noptimize--><!-- ' . $logmsg . ' --><!--/noptimize-->';
121
+ $this->content .= $logmsg;
122
+ } else {
123
+ error_log( 'Error: ' . $logmsg );
124
+ }
125
+ }
126
+
127
+ // hide everything between noptimize-comment tags
128
+ protected function hide_noptimize( $noptimize_in ) {
129
+ if ( preg_match( '/<!--\s?noptimize\s?-->/', $noptimize_in ) ) {
130
+ $noptimize_out = preg_replace_callback(
131
+ '#<!--\s?noptimize\s?-->.*?<!--\s?/\s?noptimize\s?-->#is',
132
+ function ( $matches ) {
133
+ return '%%NOPTIMIZE' . breeze_HASH . '%%' . base64_encode( $matches[0] ) . '%%NOPTIMIZE%%';
134
+ },
135
+ $noptimize_in
136
+ );
137
+ } else {
138
+ $noptimize_out = $noptimize_in;
139
+ }
140
+
141
+ return $noptimize_out;
142
+ }
143
+
144
+ // unhide noptimize-tags
145
+ protected function restore_noptimize( $noptimize_in ) {
146
+ if ( strpos( $noptimize_in, '%%NOPTIMIZE%%' ) !== false ) {
147
+ $noptimize_out = preg_replace_callback(
148
+ '#%%NOPTIMIZE' . breeze_HASH . '%%(.*?)%%NOPTIMIZE%%#is',
149
+ function ( $matches ) {
150
+ return base64_decode( $matches[1] );
151
+ },
152
+ $noptimize_in
153
+ );
154
+ } else {
155
+ $noptimize_out = $noptimize_in;
156
+ }
157
+
158
+ return $noptimize_out;
159
+ }
160
+
161
+ protected function hide_iehacks( $iehacks_in ) {
162
+ if ( strpos( $iehacks_in, '<!--[if' ) !== false ) {
163
+ $iehacks_out = preg_replace_callback(
164
+ '#<!--\[if.*?\[endif\]-->#is',
165
+ function ( $matches ) {
166
+ return '%%IEHACK' . breeze_HASH . '%%' . base64_encode( $matches[0] ) . '%%IEHACK%%';
167
+ },
168
+ $iehacks_in
169
+ );
170
+ } else {
171
+ $iehacks_out = $iehacks_in;
172
+ }
173
+
174
+ return $iehacks_out;
175
+ }
176
+
177
+ protected function restore_iehacks( $iehacks_in ) {
178
+ if ( strpos( $iehacks_in, '%%IEHACK%%' ) !== false ) {
179
+ $iehacks_out = preg_replace_callback(
180
+ '#%%IEHACK' . breeze_HASH . '%%(.*?)%%IEHACK%%#is',
181
+ function ( $matches ) {
182
+ return base64_decode( $matches[1] );
183
+ },
184
+ $iehacks_in
185
+ );
186
+ } else {
187
+ $iehacks_out = $iehacks_in;
188
+ }
189
+
190
+ return $iehacks_out;
191
+ }
192
+
193
+ protected function hide_comments( $comments_in ) {
194
+ if ( strpos( $comments_in, '<!--' ) !== false ) {
195
+ $comments_out = preg_replace_callback(
196
+ '#<!--.*?-->#is',
197
+ function ( $matches ) {
198
+ return '%%COMMENTS' . breeze_HASH . '%%' . base64_encode( $matches[0] ) . '%%COMMENTS%%';
199
+ },
200
+ $comments_in
201
+ );
202
+ } else {
203
+ $comments_out = $comments_in;
204
+ }
205
+
206
+ return $comments_out;
207
+ }
208
+
209
+ protected function restore_comments( $comments_in ) {
210
+ if ( strpos( $comments_in, '%%COMMENTS%%' ) !== false ) {
211
+ $comments_out = preg_replace_callback(
212
+ '#%%COMMENTS' . breeze_HASH . '%%(.*?)%%COMMENTS%%#is',
213
+ function ( $matches ) {
214
+ return base64_decode( $matches[1] );
215
+ },
216
+ $comments_in
217
+ );
218
+ } else {
219
+ $comments_out = $comments_in;
220
+ }
221
+
222
+ return $comments_out;
223
+ }
224
+
225
+ protected function url_replace_cdn( $url ) {
226
+ $cdn_url = apply_filters( 'breeze_filter_base_cdnurl', $this->cdn_url );
227
+ if ( ! empty( $cdn_url ) ) {
228
+ // secondly prepend domain-less absolute URL's
229
+ if ( ( substr( $url, 0, 1 ) === '/' ) && ( substr( $url, 1, 1 ) !== '/' ) ) {
230
+ $url = rtrim( $cdn_url, '/' ) . $url;
231
+ } else {
232
+ // get WordPress base URL
233
+ $WPSiteBreakdown = parse_url( breeze_WP_SITE_URL );
234
+ $WPBaseUrl = $WPSiteBreakdown['scheme'] . '://' . $WPSiteBreakdown['host'];
235
+ if ( ! empty( $WPSiteBreakdown['port'] ) ) {
236
+ $WPBaseUrl .= ':' . $WPSiteBreakdown['port'];
237
+ }
238
+ // three: replace full url's with scheme
239
+ $tmp_url = str_replace( $WPBaseUrl, rtrim( $cdn_url, '/' ), $url );
240
+ if ( $tmp_url === $url ) {
241
+ // last attempt; replace scheme-less URL's
242
+ $url = str_replace( preg_replace( '/https?:/', '', $WPBaseUrl ), rtrim( $cdn_url, '/' ), $url );
243
+ } else {
244
+ $url = $tmp_url;
245
+ }
246
+ }
247
+ }
248
+
249
+ // allow API filter to take alter after CDN replacement
250
+ $url = apply_filters( 'breeze_filter_base_replace_cdn', $url );
251
+
252
+ return $url;
253
+ }
254
+
255
+ protected function inject_in_html( $payload, $replaceTag ) {
256
+ if ( strpos( $this->content, $replaceTag[0] ) !== false ) {
257
+ if ( $replaceTag[1] === 'after' ) {
258
+ $replaceBlock = $replaceTag[0] . $payload;
259
+ } elseif ( $replaceTag[1] === 'replace' ) {
260
+ $replaceBlock = $payload;
261
+ } else {
262
+ $replaceBlock = $payload . $replaceTag[0];
263
+ }
264
+ $this->content = substr_replace( $this->content, $replaceBlock, strpos( $this->content, $replaceTag[0] ), strlen( $replaceTag[0] ) );
265
+ } else {
266
+ $this->content .= $payload;
267
+ if ( ! $this->tagWarning ) {
268
+ $this->content .= '<!--noptimize--><!-- breeze found a problem with the HTML in your Theme, tag ' . $replaceTag[0] . ' missing --><!--/noptimize-->';
269
+ $this->tagWarning = true;
270
+ }
271
+ }
272
+ }
273
+
274
+ protected function isremovable( $tag, $removables ) {
275
+ foreach ( $removables as $match ) {
276
+ if ( strpos( $tag, $match ) !== false ) {
277
+ return true;
278
+ }
279
+ }
280
+
281
+ return false;
282
+ }
283
+
284
+ // inject already minified code in optimized JS/CSS
285
+ protected function inject_minified( $in ) {
286
+ if ( strpos( $in, '%%INJECTLATER%%' ) !== false ) {
287
+ $out = preg_replace_callback(
288
+ '#%%INJECTLATER' . breeze_HASH . '%%(.*?)%%INJECTLATER%%#is',
289
+ function ( $matches ) {
290
+ $filepath = base64_decode( strtok( $matches[1], '|' ) );
291
+ $filecontent = file_get_contents( $filepath );
292
+ if ( empty( trim( $filecontent ) ) ) {
293
+ return '';
294
+ }
295
+
296
+ // remove BOM
297
+ $filecontent = preg_replace( "#\x{EF}\x{BB}\x{BF}#", '', $filecontent );
298
+
299
+ // remove comments and blank lines
300
+ if ( substr( $filepath, - 3, 3 ) === '.js' ) {
301
+ $filecontent = preg_replace( '#^\s*\/\/.*$#Um', '', $filecontent );
302
+ }
303
+
304
+ $filecontent = preg_replace( '#^\s*\/\*[^!].*\*\/\s?#Us', '', $filecontent );
305
+ $filecontent = preg_replace( "#(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+#", "\n", $filecontent );
306
+
307
+ // specific stuff for JS-files
308
+ if ( substr( $filepath, - 3, 3 ) === '.js' ) {
309
+ if ( ( substr( $filecontent, - 1, 1 ) !== ';' ) && ( substr( $filecontent, - 1, 1 ) !== '}' ) ) {
310
+ $filecontent .= ';';
311
+ }
312
+
313
+ if ( get_option( 'breeze_js_trycatch' ) === 'on' ) {
314
+ $filecontent = 'try{' . $filecontent . '}catch(e){}';
315
+ }
316
+ } elseif ( ( substr( $filepath, - 4, 4 ) === '.css' ) ) {
317
+ $filecontent = Breeze_MinificationStyles::fixurls( $filepath, $filecontent );
318
+ }
319
+
320
+ // return
321
+ return "\n" . $filecontent;
322
+ },
323
+ $in
324
+ );
325
+ } else {
326
+ $out = $in;
327
+ }
328
+
329
+ return $out;
330
+ }
331
+
332
+ /**
333
+ * Handles clear cache for the situation where cache files do not exist.
334
+ * @since 1.1.3
335
+ */
336
+ protected function clear_cache_data() {
337
+ //delete minify
338
+ Breeze_MinificationCache::clear_minification();
339
+ //clear normal cache
340
+ Breeze_PurgeCache::breeze_cache_flush();
341
+
342
+ //Breeze_PurgeCache::factory();
343
+ //clear varnish cache
344
+ $varnish_cache = new Breeze_PurgeVarnish();
345
+
346
+ $is_network = ( is_network_admin() || ( ! empty( $_POST['is_network'] ) && 'true' === $_POST['is_network'] ) );
347
+
348
+ if ( is_multisite() && $is_network ) {
349
+ $sites = get_sites();
350
+ foreach ( $sites as $site ) {
351
+ switch_to_blog( $site->blog_id );
352
+ $homepage = home_url() . '/?breeze';
353
+ $varnish_cache->purge_cache( $homepage );
354
+ restore_current_blog();
355
+ }
356
+ } else {
357
+ $homepage = home_url() . '/?breeze';
358
+ $varnish_cache->purge_cache( $homepage );
359
+ }
360
+ }
361
+
362
+ /**
363
+ * Helps to check if the cache file actually exists.
364
+ *
365
+ * @param string $file_path Full file path.
366
+ *
367
+ * @return bool
368
+ * @since 1.1.3
369
+ */
370
+ protected function is_cache_file_present( $file_path = '' ) {
371
+ if ( file_exists( $file_path ) ) {
372
+ return true;
373
+ }
374
+
375
+ return false;
376
+ }
377
+
378
+ public function get_cache_file_url( $type = 'css' ) {
379
+ $cache_dir = BREEZE_MINIFICATION_CACHE . breeze_current_user_type() . ( ! empty( $type ) ? $type . '/' : '' );
380
+ if ( is_multisite() ) {
381
+ $blog_id = get_current_blog_id();
382
+ $cache_dir = BREEZE_MINIFICATION_CACHE . $blog_id . '/' . breeze_current_user_type() . ( ! empty( $type ) ? $type . '/' : '' );
383
+ }
384
+
385
+ return $cache_dir;
386
+ }
387
+ }
 
 
 
 
 
 
 
inc/minification/breeze-minification-cache.php CHANGED
@@ -1,368 +1,357 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit;
4
- } // Exit if accessed directly
5
- /*
6
- * Based on some work of autoptimize plugin
7
- */
8
-
9
- class Breeze_MinificationCache {
10
- private $filename;
11
- private $mime;
12
- private $cachedir;
13
- private $delayed;
14
-
15
- public function __construct( $md5, $ext = 'php' ) {
16
- $this->cachedir = BREEZE_MINIFICATION_CACHE . breeze_current_user_type();
17
- if ( is_multisite() ) {
18
- $blog_id = get_current_blog_id();
19
- $this->cachedir = BREEZE_MINIFICATION_CACHE . $blog_id . '/' . breeze_current_user_type();
20
- }
21
-
22
- $this->delayed = BREEZE_CACHE_DELAY;
23
- $this->nogzip = BREEZE_CACHE_NOGZIP;
24
- if ( $this->nogzip == false ) {
25
- $this->filename = BREEZE_CACHEFILE_PREFIX . $md5 . '.php';
26
- } else {
27
- if ( in_array( $ext, array( "js", "css" ) ) ) {
28
- $this->filename = $ext . '/' . BREEZE_CACHEFILE_PREFIX . $md5 . '.' . $ext;
29
- } else {
30
- $this->filename = '/' . BREEZE_CACHEFILE_PREFIX . $md5 . '.' . $ext;
31
- }
32
- }
33
-
34
-
35
- }
36
-
37
- public function get_cache_dir(){
38
- return $this->cachedir;
39
- }
40
-
41
- public function get_file_name(){
42
- return $this->filename;
43
- }
44
-
45
- public function check() {
46
- if ( ! file_exists( $this->cachedir . $this->filename ) ) {
47
-
48
- // No cached file, sorry
49
- return false;
50
- }
51
-
52
- // Cache exists!
53
- return true;
54
- }
55
-
56
- public function retrieve() {
57
- if ( $this->check() ) {
58
- if ( $this->nogzip == false ) {
59
- return file_get_contents( $this->cachedir . $this->filename . '.none' );
60
- } else {
61
- return file_get_contents( $this->cachedir . $this->filename );
62
- }
63
- }
64
-
65
- return false;
66
- }
67
-
68
- public function cache( $code, $mime ) {
69
- if ( $this->nogzip == false ) {
70
- $file = ( $this->delayed ? 'delayed.php' : 'default.php' );
71
- $phpcode = file_get_contents( BREEZE_PLUGIN_DIR . '/inc/minification/config/' . $file );
72
- $phpcode = str_replace( array( '%%CONTENT%%', 'exit;' ), array( $mime, '' ), $phpcode );
73
-
74
-
75
- //file_put_contents( $this->cachedir . $this->filename, $phpcode, LOCK_EX );
76
- breeze_read_write_file( $this->cachedir . $this->filename, $phpcode );
77
-
78
- // file_put_contents( $this->cachedir . $this->filename . '.none', $code, LOCK_EX );
79
- breeze_read_write_file( $this->cachedir . $this->filename . '.none', $code );
80
-
81
- if ( ! $this->delayed ) {
82
- // Compress now!
83
- // file_put_contents( $this->cachedir . $this->filename . '.deflate', gzencode( $code, 9, FORCE_DEFLATE ), LOCK_EX );
84
- breeze_read_write_file( $this->cachedir . $this->filename . '.deflate', gzencode( $code, 9, FORCE_DEFLATE ) );
85
-
86
- // file_put_contents( $this->cachedir . $this->filename . '.gzip', gzencode( $code, 9, FORCE_GZIP ), LOCK_EX );
87
- breeze_read_write_file( $this->cachedir . $this->filename . '.deflate', gzencode( $code, 9, FORCE_DEFLATE ) );
88
- }
89
- } else {
90
- // Write code to cache without doing anything else
91
- // file_put_contents( $this->cachedir . $this->filename, $code, LOCK_EX );
92
- breeze_read_write_file( $this->cachedir . $this->filename, $code );
93
- }
94
- }
95
-
96
- public function getname() {
97
- apply_filters( 'breeze_filter_cache_getname', breeze_CACHE_URL . breeze_current_user_type() . $this->filename );
98
-
99
- return $this->filename;
100
- }
101
-
102
- //create folder cache
103
- public static function create_cache_minification_folder() {
104
- if ( ! defined( 'BREEZE_MINIFICATION_CACHE' ) ) {
105
- // We didn't set a cache
106
- return false;
107
- }
108
- if ( is_multisite() ) {
109
- $blog_id = get_current_blog_id();
110
- foreach ( array( "", "js", "css" ) as $checkDir ) {
111
- if ( ! Breeze_MinificationCache::checkCacheDir( BREEZE_MINIFICATION_CACHE . $blog_id . '/' . breeze_current_user_type() . $checkDir ) ) {
112
- return false;
113
- }
114
- }
115
-
116
- /** write index.html here to avoid prying eyes */
117
- $indexFile = BREEZE_MINIFICATION_CACHE . $blog_id . '/' . breeze_current_user_type() . '/index.html';
118
- if ( ! is_file( $indexFile ) ) {
119
- //@file_put_contents( $indexFile, '<html><head><meta name="robots" content="noindex, nofollow"></head><body></body></html>' );
120
- breeze_read_write_file($indexFile, '<html><head><meta name="robots" content="noindex, nofollow"></head><body></body></html>');
121
- }
122
-
123
- /** write .htaccess here to overrule wp_super_cache */
124
- $htAccess = BREEZE_MINIFICATION_CACHE . $blog_id . '/' . breeze_current_user_type() . '.htaccess';
125
- } else {
126
- foreach ( array( "", "js", "css" ) as $checkDir ) {
127
- if ( ! Breeze_MinificationCache::checkCacheDir( BREEZE_MINIFICATION_CACHE . breeze_current_user_type() . $checkDir ) ) {
128
- return false;
129
- }
130
- }
131
- /** write index.html here to avoid prying eyes */
132
- $indexFile = BREEZE_MINIFICATION_CACHE . breeze_current_user_type() . '/index.html';
133
- if ( ! is_file( $indexFile ) ) {
134
- //@file_put_contents( $indexFile, '<html><head><meta name="robots" content="noindex, nofollow"></head><body></body></html>' );
135
- breeze_read_write_file($indexFile, '<html><head><meta name="robots" content="noindex, nofollow"></head><body></body></html>');
136
- }
137
-
138
- /** write .htaccess here to overrule wp_super_cache */
139
- $htAccess = BREEZE_MINIFICATION_CACHE . breeze_current_user_type() . '/.htaccess';
140
- }
141
-
142
- if ( ! is_file( $htAccess ) ) {
143
- /**
144
- * create wp-content/AO_htaccess_tmpl with
145
- * whatever htaccess rules you might need
146
- * if you want to override default AO htaccess
147
- */
148
- $htaccess_tmpl = WP_CONTENT_DIR . "/AO_htaccess_tmpl";
149
- if ( is_file( $htaccess_tmpl ) ) {
150
- $htAccessContent = file_get_contents( $htaccess_tmpl );
151
- } else if ( is_multisite() ) {
152
- $htAccessContent = '<IfModule mod_headers.c>
153
- Header set Vary "Accept-Encoding"
154
- Header set Cache-Control "max-age=10672000, must-revalidate"
155
- </IfModule>
156
- <IfModule mod_expires.c>
157
- ExpiresActive On
158
- ExpiresByType text/css A30672000
159
- ExpiresByType text/javascript A30672000
160
- ExpiresByType application/javascript A30672000
161
- </IfModule>
162
- <IfModule mod_deflate.c>
163
- <FilesMatch "\.(js|css)$">
164
- SetOutputFilter DEFLATE
165
- </FilesMatch>
166
- </IfModule>
167
- <IfModule mod_authz_core.c>
168
- <Files *.php>
169
- Require all granted
170
- </Files>
171
- </IfModule>
172
- <IfModule !mod_authz_core.c>
173
- <Files *.php>
174
- Order allow,deny
175
- Allow from all
176
- </Files>
177
- </IfModule>';
178
- } else {
179
- $htAccessContent = '<IfModule mod_headers.c>
180
- Header set Vary "Accept-Encoding"
181
- Header set Cache-Control "max-age=10672000, must-revalidate"
182
- </IfModule>
183
- <IfModule mod_expires.c>
184
- ExpiresActive On
185
- ExpiresByType text/css A30672000
186
- ExpiresByType text/javascript A30672000
187
- ExpiresByType application/javascript A30672000
188
- </IfModule>
189
- <IfModule mod_deflate.c>
190
- <FilesMatch "\.(js|css)$">
191
- SetOutputFilter DEFLATE
192
- </FilesMatch>
193
- </IfModule>
194
- <IfModule mod_authz_core.c>
195
- <Files *.php>
196
- Require all denied
197
- </Files>
198
- </IfModule>
199
- <IfModule !mod_authz_core.c>
200
- <Files *.php>
201
- Order deny,allow
202
- Deny from all
203
- </Files>
204
- </IfModule>';
205
- }
206
-
207
- @file_put_contents( $htAccess, $htAccessContent );
208
- }
209
-
210
- // All OK
211
- return true;
212
-
213
- }
214
-
215
- // check dir cache
216
- static function checkCacheDir( $dir ) {
217
- // Check and create if not exists
218
- if ( ! file_exists( $dir ) ) {
219
- @mkdir( $dir, 0775, true );
220
- if ( ! file_exists( $dir ) ) {
221
- return false;
222
- }
223
- }
224
-
225
- // check if we can now write
226
- if ( ! is_writable( $dir ) ) {
227
- return false;
228
- }
229
-
230
- // and write index.html here to avoid prying eyes
231
- $indexFile = $dir . '/index.html';
232
- if ( ! is_file( $indexFile ) ) {
233
- @file_put_contents( $indexFile, '<html><head><meta name="robots" content="noindex, nofollow"></head><body></body></html>' );
234
- }
235
-
236
- return true;
237
- }
238
-
239
- public static function clear_minification() {
240
- if ( is_multisite() && is_network_admin() ) {
241
- $sites = get_sites(
242
- array(
243
- 'fields' => 'ids',
244
- )
245
- );
246
- foreach ( $sites as $blog_id ) {
247
- switch_to_blog( $blog_id );
248
- self::clear_site_minification();
249
- restore_current_blog();
250
- }
251
-
252
- } else {
253
- self::clear_site_minification();
254
- }
255
- }
256
-
257
- public static function clear_site_minification() {
258
- if ( ! isset( $_GET['breeze_purge'] ) && ! Breeze_MinificationCache::create_cache_minification_folder() ) {
259
- return false;
260
- }
261
- if ( ! isset( $scan ) ) {
262
- $scan = array();
263
- }
264
- $cache_folders = breeze_all_user_folders();
265
-
266
- if ( is_multisite() ) {
267
- $blog_id = get_current_blog_id();
268
- // scan the cachedirs
269
- foreach ( $cache_folders as $user_folder ) {
270
- foreach ( array( "", "js", "css" ) as $scandirName ) {
271
- $directory = BREEZE_MINIFICATION_CACHE . $blog_id . '/' . ( ! empty( $user_folder ) ? $user_folder . '/' : '' ) . $scandirName;
272
-
273
- if ( is_dir( $directory ) ) {
274
-
275
- $files_list = scandir( $directory );
276
- if ( ! empty( $files_list ) ) {
277
- if ( ! isset( $scan[ $scandirName ] ) ) {
278
- $scan[ $scandirName ] = array();
279
- }
280
-
281
- foreach ( $files_list as $index => $filename ) {
282
- if ( ! in_array( $filename, $scan[ $scandirName ] ) ) {
283
- $scan[ $scandirName ][] = $filename;
284
- }
285
- }
286
-
287
- }
288
-
289
- }
290
- }
291
- }
292
-
293
- // clear the cachedirs
294
- foreach ( $cache_folders as $user_folder ) {
295
- foreach ( $scan as $scandirName => $scanneddir ) {
296
- $thisAoCacheDir = rtrim( BREEZE_MINIFICATION_CACHE . $blog_id . '/' . ( ! empty( $user_folder ) ? $user_folder . '/' : '' ) . $scandirName, "/" ) . "/";
297
-
298
- foreach ( $scanneddir as $file ) {
299
- if ( ! in_array( $file, array( '.', '..' ) ) && ( strpos( $file, 'lock' ) !== false || strpos( $file, BREEZE_CACHEFILE_PREFIX ) !== false) && is_file( $thisAoCacheDir . $file ) ) {
300
- @unlink( $thisAoCacheDir . $file );
301
- }
302
- }
303
-
304
- @unlink( BREEZE_MINIFICATION_CACHE . $blog_id . '/' . ( ! empty( $user_folder ) ? $user_folder . '/' : '' ) . ".htaccess" );
305
- @unlink( BREEZE_MINIFICATION_CACHE . $blog_id . '/' . ( ! empty( $user_folder ) ? $user_folder . '/' : '' ) . "process.lock" );
306
- }
307
- }
308
-
309
-
310
- } else {
311
-
312
- // scan the cachedirs
313
- foreach ( $cache_folders as $user_folder ) {
314
- foreach ( array( "", "js", "css" ) as $scandirName ) {
315
- $directory = BREEZE_MINIFICATION_CACHE . ( ! empty( $user_folder ) ? $user_folder . '/' : '' ) . $scandirName;
316
-
317
- if ( is_dir( $directory ) ) {
318
- $files_list = scandir( $directory );
319
- if ( ! empty( $files_list ) ) {
320
- if ( ! isset( $scan[ $scandirName ] ) ) {
321
- $scan[ $scandirName ] = array();
322
- }
323
-
324
- foreach ( $files_list as $index => $filename ) {
325
- if ( ! in_array( $filename, $scan[ $scandirName ] ) ) {
326
- $scan[ $scandirName ][] = $filename;
327
- }
328
- }
329
-
330
- }
331
- }
332
-
333
- }
334
- }
335
-
336
- // clear the cachedirs
337
- foreach ( $cache_folders as $user_folder ) {
338
- foreach ( $scan as $scandirName => $scanneddir ) {
339
- $thisAoCacheDir = rtrim( BREEZE_MINIFICATION_CACHE . ( ! empty( $user_folder ) ? $user_folder . '/' : '' ) . $scandirName, "/" ) . "/";
340
-
341
- foreach ( $scanneddir as $file ) {
342
- if ( ! in_array( $file, array( '.', '..' ) ) && ( strpos( $file, 'lock' ) !== false || strpos( $file, BREEZE_CACHEFILE_PREFIX ) !== false) && is_file( $thisAoCacheDir . $file ) ) {
343
- @unlink( $thisAoCacheDir . $file );
344
- }
345
- }
346
- }
347
- @unlink( BREEZE_MINIFICATION_CACHE . ( ! empty( $user_folder ) ? $user_folder . '/' : '' ) . ".htaccess" );
348
- @unlink( BREEZE_MINIFICATION_CACHE . ( ! empty( $user_folder ) ? $user_folder . '/' : '' ) . "process.lock" );
349
- }
350
-
351
-
352
- }
353
-
354
- return true;
355
- }
356
-
357
- public static function factory() {
358
-
359
- static $instance;
360
-
361
- if ( ! $instance ) {
362
- $instance = new self();
363
- $instance->set_action();
364
- }
365
-
366
- return $instance;
367
- }
368
- }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit;
4
+ } // Exit if accessed directly
5
+ /*
6
+ * Based on some work of autoptimize plugin
7
+ */
8
+
9
+ class Breeze_MinificationCache {
10
+ private $filename;
11
+ private $mime;
12
+ private $cachedir;
13
+ private $delayed;
14
+
15
+ public function __construct( $md5, $ext = 'php' ) {
16
+ $this->cachedir = BREEZE_MINIFICATION_CACHE . breeze_current_user_type();
17
+ if ( is_multisite() ) {
18
+ $blog_id = get_current_blog_id();
19
+ $this->cachedir = BREEZE_MINIFICATION_CACHE . $blog_id . '/' . breeze_current_user_type();
20
+ }
21
+
22
+ $this->delayed = BREEZE_CACHE_DELAY;
23
+ $this->nogzip = BREEZE_CACHE_NOGZIP;
24
+ if ( $this->nogzip == false ) {
25
+ $this->filename = BREEZE_CACHEFILE_PREFIX . $md5 . '.php';
26
+ } else {
27
+ if ( in_array( $ext, array( 'js', 'css' ) ) ) {
28
+ $this->filename = $ext . '/' . BREEZE_CACHEFILE_PREFIX . $md5 . '.' . $ext;
29
+ } else {
30
+ $this->filename = '/' . BREEZE_CACHEFILE_PREFIX . $md5 . '.' . $ext;
31
+ }
32
+ }
33
+
34
+ }
35
+
36
+ public function get_cache_dir() {
37
+ return $this->cachedir;
38
+ }
39
+
40
+ public function get_file_name() {
41
+ return $this->filename;
42
+ }
43
+
44
+ public function check() {
45
+ if ( ! file_exists( $this->cachedir . $this->filename ) ) {
46
+
47
+ // No cached file, sorry
48
+ return false;
49
+ }
50
+
51
+ // Cache exists!
52
+ return true;
53
+ }
54
+
55
+ public function retrieve() {
56
+ if ( $this->check() ) {
57
+ if ( $this->nogzip == false ) {
58
+ return file_get_contents( $this->cachedir . $this->filename . '.none' );
59
+ } else {
60
+ return file_get_contents( $this->cachedir . $this->filename );
61
+ }
62
+ }
63
+
64
+ return false;
65
+ }
66
+
67
+ public function cache( $code, $mime ) {
68
+ if ( $this->nogzip == false ) {
69
+ $file = ( $this->delayed ? 'delayed.php' : 'default.php' );
70
+ $phpcode = file_get_contents( BREEZE_PLUGIN_DIR . '/inc/minification/config/' . $file );
71
+ $phpcode = str_replace( array( '%%CONTENT%%', 'exit;' ), array( $mime, '' ), $phpcode );
72
+
73
+ //file_put_contents( $this->cachedir . $this->filename, $phpcode, LOCK_EX );
74
+ breeze_read_write_file( $this->cachedir . $this->filename, $phpcode );
75
+
76
+ // file_put_contents( $this->cachedir . $this->filename . '.none', $code, LOCK_EX );
77
+ breeze_read_write_file( $this->cachedir . $this->filename . '.none', $code );
78
+
79
+ if ( ! $this->delayed ) {
80
+ // Compress now!
81
+ // file_put_contents( $this->cachedir . $this->filename . '.deflate', gzencode( $code, 9, FORCE_DEFLATE ), LOCK_EX );
82
+ breeze_read_write_file( $this->cachedir . $this->filename . '.deflate', gzencode( $code, 9, FORCE_DEFLATE ) );
83
+
84
+ // file_put_contents( $this->cachedir . $this->filename . '.gzip', gzencode( $code, 9, FORCE_GZIP ), LOCK_EX );
85
+ breeze_read_write_file( $this->cachedir . $this->filename . '.deflate', gzencode( $code, 9, FORCE_DEFLATE ) );
86
+ }
87
+ } else {
88
+ // Write code to cache without doing anything else
89
+ // file_put_contents( $this->cachedir . $this->filename, $code, LOCK_EX );
90
+ breeze_read_write_file( $this->cachedir . $this->filename, $code );
91
+ }
92
+ }
93
+
94
+ public function getname() {
95
+ apply_filters( 'breeze_filter_cache_getname', breeze_CACHE_URL . breeze_current_user_type() . $this->filename );
96
+
97
+ return $this->filename;
98
+ }
99
+
100
+ //create folder cache
101
+ public static function create_cache_minification_folder() {
102
+ if ( ! defined( 'BREEZE_MINIFICATION_CACHE' ) ) {
103
+ // We didn't set a cache
104
+ return false;
105
+ }
106
+ if ( is_multisite() ) {
107
+ $blog_id = get_current_blog_id();
108
+ foreach ( array( '', 'js', 'css' ) as $checkDir ) {
109
+ if ( ! Breeze_MinificationCache::checkCacheDir( BREEZE_MINIFICATION_CACHE . $blog_id . '/' . breeze_current_user_type() . $checkDir ) ) {
110
+ return false;
111
+ }
112
+ }
113
+
114
+ /** write index.html here to avoid prying eyes */
115
+ $indexFile = BREEZE_MINIFICATION_CACHE . $blog_id . '/' . breeze_current_user_type() . '/index.html';
116
+ if ( ! is_file( $indexFile ) ) {
117
+ //@file_put_contents( $indexFile, '<html><head><meta name="robots" content="noindex, nofollow"></head><body></body></html>' );
118
+ breeze_read_write_file( $indexFile, '<html><head><meta name="robots" content="noindex, nofollow"></head><body></body></html>' );
119
+ }
120
+
121
+ /** write .htaccess here to overrule wp_super_cache */
122
+ $htAccess = BREEZE_MINIFICATION_CACHE . $blog_id . '/' . breeze_current_user_type() . '.htaccess';
123
+ } else {
124
+ foreach ( array( '', 'js', 'css' ) as $checkDir ) {
125
+ if ( ! Breeze_MinificationCache::checkCacheDir( BREEZE_MINIFICATION_CACHE . breeze_current_user_type() . $checkDir ) ) {
126
+ return false;
127
+ }
128
+ }
129
+ /** write index.html here to avoid prying eyes */
130
+ $indexFile = BREEZE_MINIFICATION_CACHE . breeze_current_user_type() . '/index.html';
131
+ if ( ! is_file( $indexFile ) ) {
132
+ //@file_put_contents( $indexFile, '<html><head><meta name="robots" content="noindex, nofollow"></head><body></body></html>' );
133
+ breeze_read_write_file( $indexFile, '<html><head><meta name="robots" content="noindex, nofollow"></head><body></body></html>' );
134
+ }
135
+
136
+ /** write .htaccess here to overrule wp_super_cache */
137
+ $htAccess = BREEZE_MINIFICATION_CACHE . breeze_current_user_type() . '/.htaccess';
138
+ }
139
+
140
+ if ( ! is_file( $htAccess ) ) {
141
+ /**
142
+ * create wp-content/AO_htaccess_tmpl with
143
+ * whatever htaccess rules you might need
144
+ * if you want to override default AO htaccess
145
+ */
146
+ $htaccess_tmpl = WP_CONTENT_DIR . '/AO_htaccess_tmpl';
147
+ if ( is_file( $htaccess_tmpl ) ) {
148
+ $htAccessContent = file_get_contents( $htaccess_tmpl );
149
+ } elseif ( is_multisite() ) {
150
+ $htAccessContent = '<IfModule mod_headers.c>
151
+ Header set Vary "Accept-Encoding"
152
+ Header set Cache-Control "max-age=10672000, must-revalidate"
153
+ </IfModule>
154
+ <IfModule mod_expires.c>
155
+ ExpiresActive On
156
+ ExpiresByType text/css A30672000
157
+ ExpiresByType text/javascript A30672000
158
+ ExpiresByType application/javascript A30672000
159
+ </IfModule>
160
+ <IfModule mod_deflate.c>
161
+ <FilesMatch "\.(js|css)$">
162
+ SetOutputFilter DEFLATE
163
+ </FilesMatch>
164
+ </IfModule>
165
+ <IfModule mod_authz_core.c>
166
+ <Files *.php>
167
+ Require all granted
168
+ </Files>
169
+ </IfModule>
170
+ <IfModule !mod_authz_core.c>
171
+ <Files *.php>
172
+ Order allow,deny
173
+ Allow from all
174
+ </Files>
175
+ </IfModule>';
176
+ } else {
177
+ $htAccessContent = '<IfModule mod_headers.c>
178
+ Header set Vary "Accept-Encoding"
179
+ Header set Cache-Control "max-age=10672000, must-revalidate"
180
+ </IfModule>
181
+ <IfModule mod_expires.c>
182
+ ExpiresActive On
183
+ ExpiresByType text/css A30672000
184
+ ExpiresByType text/javascript A30672000
185
+ ExpiresByType application/javascript A30672000
186
+ </IfModule>
187
+ <IfModule mod_deflate.c>
188
+ <FilesMatch "\.(js|css)$">
189
+ SetOutputFilter DEFLATE
190
+ </FilesMatch>
191
+ </IfModule>
192
+ <IfModule mod_authz_core.c>
193
+ <Files *.php>
194
+ Require all denied
195
+ </Files>
196
+ </IfModule>
197
+ <IfModule !mod_authz_core.c>
198
+ <Files *.php>
199
+ Order deny,allow
200
+ Deny from all
201
+ </Files>
202
+ </IfModule>';
203
+ }
204
+
205
+ @file_put_contents( $htAccess, $htAccessContent );
206
+ }
207
+
208
+ // All OK
209
+ return true;
210
+
211
+ }
212
+
213
+ // check dir cache
214
+ static function checkCacheDir( $dir ) {
215
+ // Check and create if not exists
216
+ if ( ! file_exists( $dir ) ) {
217
+ @mkdir( $dir, 0775, true );
218
+ if ( ! file_exists( $dir ) ) {
219
+ return false;
220
+ }
221
+ }
222
+
223
+ // check if we can now write
224
+ if ( ! is_writable( $dir ) ) {
225
+ return false;
226
+ }
227
+
228
+ // and write index.html here to avoid prying eyes
229
+ $indexFile = $dir . '/index.html';
230
+ if ( ! is_file( $indexFile ) ) {
231
+ @file_put_contents( $indexFile, '<html><head><meta name="robots" content="noindex, nofollow"></head><body></body></html>' );
232
+ }
233
+
234
+ return true;
235
+ }
236
+
237
+ public static function clear_minification() {
238
+ if ( is_multisite() && is_network_admin() ) {
239
+ $sites = get_sites(
240
+ array(
241
+ 'fields' => 'ids',
242
+ )
243
+ );
244
+ foreach ( $sites as $blog_id ) {
245
+ switch_to_blog( $blog_id );
246
+ self::clear_site_minification();
247
+ restore_current_blog();
248
+ }
249
+ } else {
250
+ self::clear_site_minification();
251
+ }
252
+ }
253
+
254
+ public static function clear_site_minification() {
255
+ if ( ! isset( $_GET['breeze_purge'] ) && ! Breeze_MinificationCache::create_cache_minification_folder() ) {
256
+ return false;
257
+ }
258
+ if ( ! isset( $scan ) ) {
259
+ $scan = array();
260
+ }
261
+ $cache_folders = breeze_all_user_folders();
262
+
263
+ if ( is_multisite() ) {
264
+ $blog_id = get_current_blog_id();
265
+ // scan the cachedirs
266
+ foreach ( $cache_folders as $user_folder ) {
267
+ foreach ( array( '', 'js', 'css' ) as $scandirName ) {
268
+ $directory = BREEZE_MINIFICATION_CACHE . $blog_id . '/' . ( ! empty( $user_folder ) ? $user_folder . '/' : '' ) . $scandirName;
269
+
270
+ if ( is_dir( $directory ) ) {
271
+
272
+ $files_list = scandir( $directory );
273
+ if ( ! empty( $files_list ) ) {
274
+ if ( ! isset( $scan[ $scandirName ] ) ) {
275
+ $scan[ $scandirName ] = array();
276
+ }
277
+
278
+ foreach ( $files_list as $index => $filename ) {
279
+ if ( ! in_array( $filename, $scan[ $scandirName ] ) ) {
280
+ $scan[ $scandirName ][] = $filename;
281
+ }
282
+ }
283
+ }
284
+ }
285
+ }
286
+ }
287
+
288
+ // clear the cachedirs
289
+ foreach ( $cache_folders as $user_folder ) {
290
+ foreach ( $scan as $scandirName => $scanneddir ) {
291
+ $thisAoCacheDir = rtrim( BREEZE_MINIFICATION_CACHE . $blog_id . '/' . ( ! empty( $user_folder ) ? $user_folder . '/' : '' ) . $scandirName, '/' ) . '/';
292
+
293
+ foreach ( $scanneddir as $file ) {
294
+ if ( ! in_array( $file, array( '.', '..' ) ) && ( strpos( $file, 'lock' ) !== false || strpos( $file, BREEZE_CACHEFILE_PREFIX ) !== false ) && is_file( $thisAoCacheDir . $file ) ) {
295
+ @unlink( $thisAoCacheDir . $file );
296
+ }
297
+ }
298
+
299
+ @unlink( BREEZE_MINIFICATION_CACHE . $blog_id . '/' . ( ! empty( $user_folder ) ? $user_folder . '/' : '' ) . '.htaccess' );
300
+ @unlink( BREEZE_MINIFICATION_CACHE . $blog_id . '/' . ( ! empty( $user_folder ) ? $user_folder . '/' : '' ) . 'process.lock' );
301
+ }
302
+ }
303
+ } else {
304
+
305
+ // scan the cachedirs
306
+ foreach ( $cache_folders as $user_folder ) {
307
+ foreach ( array( '', 'js', 'css' ) as $scandirName ) {
308
+ $directory = BREEZE_MINIFICATION_CACHE . ( ! empty( $user_folder ) ? $user_folder . '/' : '' ) . $scandirName;
309
+
310
+ if ( is_dir( $directory ) ) {
311
+ $files_list = scandir( $directory );
312
+ if ( ! empty( $files_list ) ) {
313
+ if ( ! isset( $scan[ $scandirName ] ) ) {
314
+ $scan[ $scandirName ] = array();
315
+ }
316
+
317
+ foreach ( $files_list as $index => $filename ) {
318
+ if ( ! in_array( $filename, $scan[ $scandirName ] ) ) {
319
+ $scan[ $scandirName ][] = $filename;
320
+ }
321
+ }
322
+ }
323
+ }
324
+ }
325
+ }
326
+
327
+ // clear the cachedirs
328
+ foreach ( $cache_folders as $user_folder ) {
329
+ foreach ( $scan as $scandirName => $scanneddir ) {
330
+ $thisAoCacheDir = rtrim( BREEZE_MINIFICATION_CACHE . ( ! empty( $user_folder ) ? $user_folder . '/' : '' ) . $scandirName, '/' ) . '/';
331
+
332
+ foreach ( $scanneddir as $file ) {
333
+ if ( ! in_array( $file, array( '.', '..' ) ) && ( strpos( $file, 'lock' ) !== false || strpos( $file, BREEZE_CACHEFILE_PREFIX ) !== false ) && is_file( $thisAoCacheDir . $file ) ) {
334
+ @unlink( $thisAoCacheDir . $file );
335
+ }
336
+ }
337
+ }
338
+ @unlink( BREEZE_MINIFICATION_CACHE . ( ! empty( $user_folder ) ? $user_folder . '/' : '' ) . '.htaccess' );
339
+ @unlink( BREEZE_MINIFICATION_CACHE . ( ! empty( $user_folder ) ? $user_folder . '/' : '' ) . 'process.lock' );
340
+ }
341
+ }
342
+
343
+ return true;
344
+ }
345
+
346
+ public static function factory() {
347
+
348
+ static $instance;
349
+
350
+ if ( ! $instance ) {
351
+ $instance = new self();
352
+ $instance->set_action();
353
+ }
354
+
355
+ return $instance;
356
+ }
357
+ }
 
 
 
 
 
 
 
 
 
 
 
inc/minification/breeze-minification-html.php CHANGED
@@ -1,120 +1,120 @@
1
- <?php
2
- /*
3
- * Based on some work of autoptimize plugin
4
- */
5
- if ( ! defined( 'ABSPATH' ) ) {
6
- exit;
7
- } // Exit if accessed directly
8
-
9
- class Breeze_MinificationHtml extends Breeze_MinificationBase {
10
- private $keepcomments = false;
11
- private $exclude = array( '<!-- ngg_resource_manager_marker -->' );
12
- private $original_content = '';
13
- private $show_original_content = 0;
14
- private $do_process = false;
15
-
16
- public function read( $options ) {
17
- $this_path_url = $this->get_cache_file_url( '' );
18
- if ( false === breeze_is_process_locked( $this_path_url ) ) {
19
- $this->do_process = breeze_lock_cache_process( $this_path_url );
20
- } else {
21
- $this->original_content = $this->content;
22
-
23
- return true;
24
- }
25
-
26
- // Remove the HTML comments?
27
- $this->keepcomments = (bool) $options['keepcomments'];
28
-
29
- // filter to force xhtml
30
- $this->forcexhtml = (bool) apply_filters( 'breeze_filter_html_forcexhtml', false );
31
-
32
- // filter to add strings to be excluded from HTML minification
33
- $excludeHTML = apply_filters( 'breeze_filter_html_exclude', '' );
34
- if ( $excludeHTML !== "" ) {
35
- $exclHTMLArr = array_filter( array_map( 'trim', explode( ",", $excludeHTML ) ) );
36
- $this->exclude = array_merge( $exclHTMLArr, $this->exclude );
37
- }
38
-
39
- // Nothing else for HTML
40
- return true;
41
- }
42
-
43
- //Joins and optimizes CSS
44
- public function minify() {
45
- if ( false === $this->do_process ) {
46
- return true;
47
- }
48
-
49
- $noptimizeHTML = apply_filters( 'breeze_filter_html_noptimize', false, $this->content );
50
- if ( $noptimizeHTML ) {
51
- return false;
52
- }
53
-
54
- if ( class_exists( 'Minify_HTML' ) ) {
55
- // wrap the to-be-excluded strings in noptimize tags
56
- foreach ( $this->exclude as $exclString ) {
57
- if ( strpos( $this->content, $exclString ) !== false ) {
58
- $replString = "<!--noptimize-->" . $exclString . "<!--/noptimize-->";
59
- $this->content = str_replace( $exclString, $replString, $this->content );
60
- }
61
- }
62
-
63
- // noptimize me
64
- $this->content = $this->hide_noptimize( $this->content );
65
-
66
- // Minify html
67
- $options = array( 'keepComments' => $this->keepcomments );
68
- if ( $this->forcexhtml ) {
69
- $options['xhtml'] = true;
70
- }
71
-
72
- if ( method_exists( 'Minify_HTML', 'minify' ) ) {
73
- $tmp_content = Minify_HTML::minify( $this->content, $options );
74
- if ( ! empty( $tmp_content ) ) {
75
- $this->content = $tmp_content;
76
- unset( $tmp_content );
77
- }
78
- }
79
-
80
- // restore noptimize
81
- $this->content = $this->restore_noptimize( $this->content );
82
-
83
- // remove the noptimize-wrapper from around the excluded strings
84
- foreach ( $this->exclude as $exclString ) {
85
- $replString = "<!--noptimize-->" . $exclString . "<!--/noptimize-->";
86
- if ( strpos( $this->content, $replString ) !== false ) {
87
- $this->content = str_replace( $replString, $exclString, $this->content );
88
- }
89
- }
90
-
91
- return true;
92
- }
93
-
94
- // Didn't minify :(
95
- return false;
96
- }
97
-
98
- // Does nothing
99
- public function cache() {
100
- //No cache for HTML
101
- return true;
102
- }
103
-
104
- //Returns the content
105
- public function getcontent() {
106
- if ( ! empty( $this->show_original_content ) ) {
107
- return $this->original_content;
108
- }
109
-
110
- if ( true === $this->do_process ) {
111
- $this_path_url = $this->get_cache_file_url( '' );
112
- breeze_unlock_process( $this_path_url );
113
- return $this->content;
114
- } else {
115
- return $this->original_content;
116
- }
117
-
118
- //return $this->content;
119
- }
120
- }
1
+ <?php
2
+ /*
3
+ * Based on some work of autoptimize plugin
4
+ */
5
+ if ( ! defined( 'ABSPATH' ) ) {
6
+ exit;
7
+ } // Exit if accessed directly
8
+
9
+ class Breeze_MinificationHtml extends Breeze_MinificationBase {
10
+ private $keepcomments = false;
11
+ private $exclude = array( '<!-- ngg_resource_manager_marker -->' );
12
+ private $original_content = '';
13
+ private $show_original_content = 0;
14
+ private $do_process = false;
15
+
16
+ public function read( $options ) {
17
+ $this_path_url = $this->get_cache_file_url( '' );
18
+ if ( false === breeze_is_process_locked( $this_path_url ) ) {
19
+ $this->do_process = breeze_lock_cache_process( $this_path_url );
20
+ } else {
21
+ $this->original_content = $this->content;
22
+
23
+ return true;
24
+ }
25
+
26
+ // Remove the HTML comments?
27
+ $this->keepcomments = (bool) $options['keepcomments'];
28
+
29
+ // filter to force xhtml
30
+ $this->forcexhtml = (bool) apply_filters( 'breeze_filter_html_forcexhtml', false );
31
+
32
+ // filter to add strings to be excluded from HTML minification
33
+ $excludeHTML = apply_filters( 'breeze_filter_html_exclude', '' );
34
+ if ( $excludeHTML !== '' ) {
35
+ $exclHTMLArr = array_filter( array_map( 'trim', explode( ',', $excludeHTML ) ) );
36
+ $this->exclude = array_merge( $exclHTMLArr, $this->exclude );
37
+ }
38
+
39
+ // Nothing else for HTML
40
+ return true;
41
+ }
42
+
43
+ //Joins and optimizes CSS
44
+ public function minify() {
45
+ if ( false === $this->do_process ) {
46
+ return true;
47
+ }
48
+
49
+ $noptimizeHTML = apply_filters( 'breeze_filter_html_noptimize', false, $this->content );
50
+ if ( $noptimizeHTML ) {
51
+ return false;
52
+ }
53
+
54
+ if ( class_exists( 'Minify_HTML' ) ) {
55
+ // wrap the to-be-excluded strings in noptimize tags
56
+ foreach ( $this->exclude as $exclString ) {
57
+ if ( strpos( $this->content, $exclString ) !== false ) {
58
+ $replString = '<!--noptimize-->' . $exclString . '<!--/noptimize-->';
59
+ $this->content = str_replace( $exclString, $replString, $this->content );
60
+ }
61
+ }
62
+
63
+ // noptimize me
64
+ $this->content = $this->hide_noptimize( $this->content );
65
+
66
+ // Minify html
67
+ $options = array( 'keepComments' => $this->keepcomments );
68
+ if ( $this->forcexhtml ) {
69
+ $options['xhtml'] = true;
70
+ }
71
+
72
+ if ( method_exists( 'Minify_HTML', 'minify' ) ) {
73
+ $tmp_content = Minify_HTML::minify( $this->content, $options );
74
+ if ( ! empty( $tmp_content ) ) {
75
+ $this->content = $tmp_content;
76
+ unset( $tmp_content );
77
+ }
78
+ }
79
+
80
+ // restore noptimize
81
+ $this->content = $this->restore_noptimize( $this->content );
82
+
83
+ // remove the noptimize-wrapper from around the excluded strings
84
+ foreach ( $this->exclude as $exclString ) {
85
+ $replString = '<!--noptimize-->' . $exclString . '<!--/noptimize-->';
86
+ if ( strpos( $this->content, $replString ) !== false ) {
87
+ $this->content = str_replace( $replString, $exclString, $this->content );
88
+ }
89
+ }
90
+
91
+ return true;
92
+ }
93
+
94
+ // Didn't minify :(
95
+ return false;
96
+ }
97
+
98
+ // Does nothing
99
+ public function cache() {
100
+ //No cache for HTML
101
+ return true;
102
+ }
103
+
104
+ //Returns the content
105
+ public function getcontent() {
106
+ if ( ! empty( $this->show_original_content ) ) {
107
+ return $this->original_content;
108
+ }
109
+
110
+ if ( true === $this->do_process ) {
111
+ $this_path_url = $this->get_cache_file_url( '' );
112
+ breeze_unlock_process( $this_path_url );
113
+ return $this->content;
114
+ } else {
115
+ return $this->original_content;
116
+ }
117
+
118
+ //return $this->content;
119
+ }
120
+ }
inc/minification/breeze-minification-scripts.php CHANGED
@@ -1,17 +1,18 @@
1
  <?php
2
 
3
  use MatthiasMullie\Minify;
 
4
  /*
5
- * Based on some work of autoptimize plugin
6
  */
7
  if ( ! defined( 'ABSPATH' ) ) {
8
  exit;
9
  } // Exit if accessed directly
10
 
11
  class Breeze_MinificationScripts extends Breeze_MinificationBase {
12
- private $head_scripts = array();
13
- private $footer_scripts = array();
14
- private $dontmove = array(
15
  'gtag',
16
  'document.write',
17
  'html5.js',
@@ -44,8 +45,10 @@ class Breeze_MinificationScripts extends Breeze_MinificationBase {
44
  'post_id',
45
  'data-noptimize',
46
  );
47
- private $domove = array( 'gaJsHost', 'load_cmc', 'jd.gallery.transitions.js', 'swfobject.embedSWF(', 'tiny_mce.js', 'tinyMCEPreInit.go' );
48
- private $domovelast = array(
 
 
49
  'addthis.com',
50
  '/afsonline/show_afs_search.js',
51
  'disqus.js',
@@ -57,41 +60,42 @@ class Breeze_MinificationScripts extends Breeze_MinificationBase {
57
  'linkwithin.com/widget.js',
58
  'tiny_mce.js',
59
  'tinyMCEPreInit.go',
 
60
  );
61
- private $trycatch = false;
62
- private $alreadyminified = false;
63
- private $forcehead = true;
64
- private $include_inline = false;
65
- private $jscode = '';
66
- private $url = '';
67
- private $move = array(
68
  'first' => array(),
69
  'last' => array(),
70
  );
71
- private $restofcontent = '';
72
- private $md5hash = '';
73
- private $whitelist = '';
74
- private $jsremovables = array();
75
- private $inject_min_late = '';
76
- private $group_js = false;
77
- private $custom_js_exclude = array();
78
- private $js_head_group = array();
79
- private $js_footer_group = array();
80
- private $js_min_head = array();
81
- private $js_min_footer = array();
82
- private $url_group_head = array();
83
- private $url_group_footer = array();
84
- private $jscode_inline_head = array();
85
- private $jscode_inline_footer = array();
86
- private $move_to_footer_js = array();
87
- private $move_to_footer = array();
88
- private $defer_js = array();
89
- private $full_script = '';
90
- private $uncompressed_inline = array();
91
- private $inline_increment = 1;
92
- private $original_content = '';
93
  private $show_original_content = 0;
94
- private $do_process = false;
95
 
96
  //Reads the page and collects script tags
97
  public function read( $options ) {
@@ -215,7 +219,14 @@ class Breeze_MinificationScripts extends Breeze_MinificationBase {
215
 
216
  //Get all JS in page
217
  private function getJS( $content, $head = true ) {
 
218
  if ( preg_match_all( '#<script.*</script>#Usmi', $content, $matches ) ) {
 
 
 
 
 
 
219
  foreach ( $matches[0] as $tag ) {
220
  // only consider aggregation whitelisted in should_aggregate-function
221
  if ( ! $this->should_aggregate( $tag ) ) {
@@ -241,12 +252,14 @@ class Breeze_MinificationScripts extends Breeze_MinificationBase {
241
 
242
  // Let's check if this file is in the excluded list.
243
  $is_excluded = breeze_is_string_in_array_values( $url, $this->custom_js_exclude );
 
244
  //exclude js
245
  if ( ! empty( $is_excluded ) ) {
246
  continue;
247
  }
248
 
249
  $path = $this->getpath( $url );
 
250
  if ( $path !== false && preg_match( '#\.js$#', $path ) ) {
251
  //Inline
252
  if ( $this->ismergeable( $tag ) ) {
@@ -387,7 +400,7 @@ class Breeze_MinificationScripts extends Breeze_MinificationBase {
387
  if ( empty( $this->include_inline ) ) {
388
 
389
  $index_inline = "/*!IS_UNCOMPRESSED_INLINE_{$this->inline_increment}*/";
390
- $this->full_script .= $index_inline;
391
  $this->uncompressed_inline[ $index_inline ] = $script;
392
  $this->inline_increment ++;
393
 
@@ -413,12 +426,11 @@ class Breeze_MinificationScripts extends Breeze_MinificationBase {
413
  $scriptsrc = $tmpscriptsrc;
414
  $this->alreadyminified = true;
415
 
416
- } elseif ( ( strpos( $script, 'min.js' ) !== false ) && ( $this->inject_min_late === true ) || $this->breeze_js_files_exceptions( $url ) ) {
417
  $scriptsrc = '%%INJECTLATER' . breeze_HASH . '%%' . base64_encode( $script ) . '|' . md5( $scriptsrc ) . '%%INJECTLATER%%';
418
 
419
  }
420
 
421
-
422
  if ( $this->group_js == true ) {
423
  $this->jscode .= "\n" . $scriptsrc;
424
  $this->full_script .= "\n" . $scriptsrc;
@@ -523,7 +535,7 @@ class Breeze_MinificationScripts extends Breeze_MinificationBase {
523
  unset( $ccheck );
524
 
525
  //$this->jscode has all the uncompressed code now.
526
- if( apply_filters( 'breeze_js_do_minify', true ) ){
527
  $minifier = new Minify\JS();
528
  $minifier->add( $jscode );
529
  $tmp_jscode = $minifier->minify();
@@ -552,7 +564,7 @@ class Breeze_MinificationScripts extends Breeze_MinificationBase {
552
  unset( $ccheck );
553
 
554
  //$this->jscode has all the uncompressed code now.
555
- if( apply_filters( 'breeze_js_do_minify', true ) ){
556
  $minifier = new Minify\JS();
557
  $minifier->add( $jscode );
558
  $tmp_jscode = $minifier->minify();
@@ -595,7 +607,6 @@ class Breeze_MinificationScripts extends Breeze_MinificationBase {
595
  $this->show_original_content = 1;
596
  $this->clear_cache_data();
597
  }
598
-
599
  } else {
600
  $url_exists = true;
601
 
@@ -650,7 +661,7 @@ class Breeze_MinificationScripts extends Breeze_MinificationBase {
650
 
651
  // Restore the full content
652
  if ( ! empty( $this->restofcontent ) ) {
653
- $this->content .= $this->restofcontent;
654
  $this->restofcontent = '';
655
  }
656
 
@@ -662,7 +673,7 @@ class Breeze_MinificationScripts extends Breeze_MinificationBase {
662
  foreach ( $this->jscode_inline_head as $js ) {
663
  $jsHead[] = '<script type="text/javascript">' . $js . '</script>';
664
  }
665
- $jsReplacement = '';
666
  $jsReplacement .= implode( '', $jsHead );
667
  $this->inject_in_html( $jsReplacement, $replaceTag );
668
  }
@@ -673,7 +684,7 @@ class Breeze_MinificationScripts extends Breeze_MinificationBase {
673
  foreach ( $this->jscode_inline_footer as $js ) {
674
  $jsFooter[] = '<script type="text/javascript">' . $js . '</script>';
675
  }
676
- $jsReplacement = '';
677
  $jsReplacement .= implode( '', $jsFooter );
678
  $this->inject_in_html( $jsReplacement, $replaceTag );
679
  }
@@ -686,7 +697,7 @@ class Breeze_MinificationScripts extends Breeze_MinificationBase {
686
  $bodyreplacementpayload = '<script type="text/javascript" defer src="' . $this->url . '"></script>';
687
  $bodyreplacementpayload = apply_filters( 'breeze_filter_js_bodyreplacementpayload', $bodyreplacementpayload );
688
 
689
- $bodyreplacement = implode( '', $this->move['first'] );
690
  $bodyreplacement .= $bodyreplacementpayload;
691
  $bodyreplacement .= implode( '', $this->move['last'] );
692
 
@@ -712,7 +723,7 @@ class Breeze_MinificationScripts extends Breeze_MinificationBase {
712
  }
713
  $jsReplacementPayload = implode( '', $headScript );
714
 
715
- $jsReplacement = implode( '', $this->move['first'] );
716
  $jsReplacement .= $jsReplacementPayload;
717
 
718
  $replaceTag = apply_filters( 'breeze_filter_js_replacetag', $replaceTag );
@@ -735,7 +746,7 @@ class Breeze_MinificationScripts extends Breeze_MinificationBase {
735
  }
736
  $jsReplacementPayload = implode( '', $footerScript );
737
 
738
- $jsReplacement = $jsReplacementPayload;
739
  $jsReplacement .= implode( '', $this->move['last'] );
740
 
741
  $replaceTag = apply_filters( 'breeze_filter_js_replacetag', $replaceTag );
@@ -790,10 +801,24 @@ class Breeze_MinificationScripts extends Breeze_MinificationBase {
790
  return false;
791
  }
792
 
 
793
  foreach ( $this->dontmove as $match ) {
794
  if ( strpos( $tag, $match ) !== false ) {
795
  //Matched something
796
- return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
797
  }
798
  }
799
 
@@ -831,10 +856,23 @@ class Breeze_MinificationScripts extends Breeze_MinificationBase {
831
  }
832
 
833
  private function movetolast( $tag ) {
 
834
  foreach ( $this->domovelast as $match ) {
835
  if ( strpos( $tag, $match ) !== false ) {
836
  //Matched, return true
837
- return true;
 
 
 
 
 
 
 
 
 
 
 
 
838
  }
839
  }
840
 
1
  <?php
2
 
3
  use MatthiasMullie\Minify;
4
+
5
  /*
6
+ * Based on some work of autoptimize plugin
7
  */
8
  if ( ! defined( 'ABSPATH' ) ) {
9
  exit;
10
  } // Exit if accessed directly
11
 
12
  class Breeze_MinificationScripts extends Breeze_MinificationBase {
13
+ private $head_scripts = array();
14
+ private $footer_scripts = array();
15
+ private $dontmove = array(
16
  'gtag',
17
  'document.write',
18
  'html5.js',
45
  'post_id',
46
  'data-noptimize',
47
  );
48
+ private $donotmove_exception = array( 'jQuery' );
49
+
50
+ private $domove = array( 'gaJsHost', 'load_cmc', 'jd.gallery.transitions.js', 'swfobject.embedSWF(', 'tiny_mce.js', 'tinyMCEPreInit.go' );
51
+ private $domovelast = array(
52
  'addthis.com',
53
  '/afsonline/show_afs_search.js',
54
  'disqus.js',
60
  'linkwithin.com/widget.js',
61
  'tiny_mce.js',
62
  'tinyMCEPreInit.go',
63
+ 'post_id',
64
  );
65
+ private $trycatch = false;
66
+ private $alreadyminified = false;
67
+ private $forcehead = true;
68
+ private $include_inline = false;
69
+ private $jscode = '';
70
+ private $url = '';
71
+ private $move = array(
72
  'first' => array(),
73
  'last' => array(),
74
  );
75
+ private $restofcontent = '';
76
+ private $md5hash = '';
77
+ private $whitelist = '';
78
+ private $jsremovables = array();
79
+ private $inject_min_late = '';
80
+ private $group_js = false;
81
+ private $custom_js_exclude = array();
82
+ private $js_head_group = array();
83
+ private $js_footer_group = array();
84
+ private $js_min_head = array();
85
+ private $js_min_footer = array();
86
+ private $url_group_head = array();
87
+ private $url_group_footer = array();
88
+ private $jscode_inline_head = array();
89
+ private $jscode_inline_footer = array();
90
+ private $move_to_footer_js = array();
91
+ private $move_to_footer = array();
92
+ private $defer_js = array();
93
+ private $full_script = '';
94
+ private $uncompressed_inline = array();
95
+ private $inline_increment = 1;
96
+ private $original_content = '';
97
  private $show_original_content = 0;
98
+ private $do_process = false;
99
 
100
  //Reads the page and collects script tags
101
  public function read( $options ) {
219
 
220
  //Get all JS in page
221
  private function getJS( $content, $head = true ) {
222
+
223
  if ( preg_match_all( '#<script.*</script>#Usmi', $content, $matches ) ) {
224
+
225
+ if ( wp_script_is( 'spai-sniper', 'enqueued' ) ) {
226
+ $jquery_local_path = home_url( '/wp-includes/js/jquery/jquery.js' );
227
+ $this->custom_js_exclude[] = $jquery_local_path;
228
+ }
229
+
230
  foreach ( $matches[0] as $tag ) {
231
  // only consider aggregation whitelisted in should_aggregate-function
232
  if ( ! $this->should_aggregate( $tag ) ) {
252
 
253
  // Let's check if this file is in the excluded list.
254
  $is_excluded = breeze_is_string_in_array_values( $url, $this->custom_js_exclude );
255
+
256
  //exclude js
257
  if ( ! empty( $is_excluded ) ) {
258
  continue;
259
  }
260
 
261
  $path = $this->getpath( $url );
262
+
263
  if ( $path !== false && preg_match( '#\.js$#', $path ) ) {
264
  //Inline
265
  if ( $this->ismergeable( $tag ) ) {
400
  if ( empty( $this->include_inline ) ) {
401
 
402
  $index_inline = "/*!IS_UNCOMPRESSED_INLINE_{$this->inline_increment}*/";
403
+ $this->full_script .= $index_inline;
404
  $this->uncompressed_inline[ $index_inline ] = $script;
405
  $this->inline_increment ++;
406
 
426
  $scriptsrc = $tmpscriptsrc;
427
  $this->alreadyminified = true;
428
 
429
+ } elseif ( apply_filters( 'breeze_js_ignore_minify', $script ) || ( strpos( $script, 'min.js' ) !== false ) && ( $this->inject_min_late === true ) || $this->breeze_js_files_exceptions( $url ) ) {
430
  $scriptsrc = '%%INJECTLATER' . breeze_HASH . '%%' . base64_encode( $script ) . '|' . md5( $scriptsrc ) . '%%INJECTLATER%%';
431
 
432
  }
433
 
 
434
  if ( $this->group_js == true ) {
435
  $this->jscode .= "\n" . $scriptsrc;
436
  $this->full_script .= "\n" . $scriptsrc;
535
  unset( $ccheck );
536
 
537
  //$this->jscode has all the uncompressed code now.
538
+ if ( apply_filters( 'breeze_js_do_minify', true ) ) {
539
  $minifier = new Minify\JS();
540
  $minifier->add( $jscode );
541
  $tmp_jscode = $minifier->minify();
564
  unset( $ccheck );
565
 
566
  //$this->jscode has all the uncompressed code now.
567
+ if ( apply_filters( 'breeze_js_do_minify', true ) ) {
568
  $minifier = new Minify\JS();
569
  $minifier->add( $jscode );
570
  $tmp_jscode = $minifier->minify();
607
  $this->show_original_content = 1;
608
  $this->clear_cache_data();
609
  }
 
610
  } else {
611
  $url_exists = true;
612
 
661
 
662
  // Restore the full content
663
  if ( ! empty( $this->restofcontent ) ) {
664
+ $this->content .= $this->restofcontent;
665
  $this->restofcontent = '';
666
  }
667
 
673
  foreach ( $this->jscode_inline_head as $js ) {
674
  $jsHead[] = '<script type="text/javascript">' . $js . '</script>';
675
  }
676
+ $jsReplacement = '';
677
  $jsReplacement .= implode( '', $jsHead );
678
  $this->inject_in_html( $jsReplacement, $replaceTag );
679
  }
684
  foreach ( $this->jscode_inline_footer as $js ) {
685
  $jsFooter[] = '<script type="text/javascript">' . $js . '</script>';
686
  }
687
+ $jsReplacement = '';
688
  $jsReplacement .= implode( '', $jsFooter );
689
  $this->inject_in_html( $jsReplacement, $replaceTag );
690
  }
697
  $bodyreplacementpayload = '<script type="text/javascript" defer src="' . $this->url . '"></script>';
698
  $bodyreplacementpayload = apply_filters( 'breeze_filter_js_bodyreplacementpayload', $bodyreplacementpayload );
699
 
700
+ $bodyreplacement = implode( '', $this->move['first'] );
701
  $bodyreplacement .= $bodyreplacementpayload;
702
  $bodyreplacement .= implode( '', $this->move['last'] );
703
 
723
  }
724
  $jsReplacementPayload = implode( '', $headScript );
725
 
726
+ $jsReplacement = implode( '', $this->move['first'] );
727
  $jsReplacement .= $jsReplacementPayload;
728
 
729
  $replaceTag = apply_filters( 'breeze_filter_js_replacetag', $replaceTag );
746
  }
747
  $jsReplacementPayload = implode( '', $footerScript );
748
 
749
+ $jsReplacement = $jsReplacementPayload;
750
  $jsReplacement .= implode( '', $this->move['last'] );
751
 
752
  $replaceTag = apply_filters( 'breeze_filter_js_replacetag', $replaceTag );
801
  return false;
802
  }
803
 
804
+ $return_value = true;
805
  foreach ( $this->dontmove as $match ) {
806
  if ( strpos( $tag, $match ) !== false ) {
807
  //Matched something
808
+ $return_value = false;
809
+
810
+ }
811
+ }
812
+
813
+ if ( false === $return_value ) {
814
+
815
+ foreach ( $this->donotmove_exception as $match ) {
816
+ if ( strpos( $tag, $match ) !== false ) {
817
+ //Matched something
818
+
819
+ return true;
820
+
821
+ }
822
  }
823
  }
824
 
856
  }
857
 
858
  private function movetolast( $tag ) {
859
+ $return_value = false;
860
  foreach ( $this->domovelast as $match ) {
861
  if ( strpos( $tag, $match ) !== false ) {
862
  //Matched, return true
863
+ $return_value = true;
864
+ }
865
+ }
866
+
867
+ if ( true === $return_value ) {
868
+
869
+ foreach ( $this->donotmove_exception as $match ) {
870
+ if ( strpos( $tag, $match ) !== false ) {
871
+ //Matched something
872
+
873
+ return false;
874
+
875
+ }
876
  }
877
  }
878
 
inc/minification/breeze-minification-styles.php CHANGED
@@ -1,37 +1,37 @@
1
  <?php
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();
11
- private $url = array();
12
- private $restofcontent = '';
13
- private $mhtml = '';
14
- private $datauris = false;
15
- private $hashmap = array();
16
- private $alreadyminified = false;
17
- private $inline = false;
18
- private $defer = false;
19
- private $defer_inline = false;
20
- private $whitelist = '';
21
- private $cssinlinesize = '';
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
- private $include_imported_css = false;
32
- private $original_content = '';
33
  private $show_original_content = 0;
34
- private $do_process = false;
35
 
36
 
37
  //Reads the page and collects style tags
@@ -322,8 +322,8 @@ class Breeze_MinificationStyles extends Breeze_MinificationBase {
322
  if ( ! $import_ok ) {
323
  // external imports and general fall-back
324
  $external_imports .= $import;
325
- $thiscss = str_replace( $import, '', $thiscss );
326
- $fiximports = true;
327
  }
328
  }
329
  $thiscss = preg_replace( '#/\*FILESTART\*/#', '', $thiscss );
@@ -559,7 +559,6 @@ class Breeze_MinificationStyles extends Breeze_MinificationBase {
559
  $this->show_original_content = 1;
560
  $this->clear_cache_data();
561
  }
562
-
563
  } else {
564
  $url_exists = true;
565
  foreach ( $this->css_min_arr as $value ) {
@@ -578,7 +577,7 @@ class Breeze_MinificationStyles extends Breeze_MinificationBase {
578
  if ( ! file_exists( $cache_directory . $cache->get_file_name() ) ) {
579
  $url_exists = false;
580
  } else {
581
- $this->url_group_arr[] = $media . "_breezemedia_" . $hash . "_breezekey_" . breeze_CACHE_URL . breeze_current_user_type() . $cache->getname();
582
  }
583
  }
584
 
@@ -603,7 +602,6 @@ class Breeze_MinificationStyles extends Breeze_MinificationBase {
603
  if ( strpos( $this->content, '%%SCRIPT%%' ) !== false ) {
604
  $this->content = preg_replace_callback(
605
  '#%%SCRIPT' . breeze_HASH . '%%(.*?)%%SCRIPT%%#is',
606
-
607
  function ( $matches ) {
608
  return base64_decode( $matches[1] );
609
  },
@@ -614,7 +612,7 @@ class Breeze_MinificationStyles extends Breeze_MinificationBase {
614
  $this->content = $this->restore_noptimize( $this->content );
615
  //Restore the full content
616
  if ( ! empty( $this->restofcontent ) ) {
617
- $this->content .= $this->restofcontent;
618
  $this->restofcontent = '';
619
  }
620
  // Inject the new stylesheets
1
  <?php
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();
11
+ private $url = array();
12
+ private $restofcontent = '';
13
+ private $mhtml = '';
14
+ private $datauris = false;
15
+ private $hashmap = array();
16
+ private $alreadyminified = false;
17
+ private $inline = false;
18
+ private $defer = false;
19
+ private $defer_inline = false;
20
+ private $whitelist = '';
21
+ private $cssinlinesize = '';
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
+ private $include_imported_css = false;
32
+ private $original_content = '';
33
  private $show_original_content = 0;
34
+ private $do_process = false;
35
 
36
 
37
  //Reads the page and collects style tags
322
  if ( ! $import_ok ) {
323
  // external imports and general fall-back
324
  $external_imports .= $import;
325
+ $thiscss = str_replace( $import, '', $thiscss );
326
+ $fiximports = true;
327
  }
328
  }
329
  $thiscss = preg_replace( '#/\*FILESTART\*/#', '', $thiscss );
559
  $this->show_original_content = 1;
560
  $this->clear_cache_data();
561
  }
 
562
  } else {
563
  $url_exists = true;
564
  foreach ( $this->css_min_arr as $value ) {
577
  if ( ! file_exists( $cache_directory . $cache->get_file_name() ) ) {
578
  $url_exists = false;
579
  } else {
580
+ $this->url_group_arr[] = $media . '_breezemedia_' . $hash . '_breezekey_' . breeze_CACHE_URL . breeze_current_user_type() . $cache->getname();
581
  }
582
  }
583
 
602
  if ( strpos( $this->content, '%%SCRIPT%%' ) !== false ) {
603
  $this->content = preg_replace_callback(
604
  '#%%SCRIPT' . breeze_HASH . '%%(.*?)%%SCRIPT%%#is',
 
605
  function ( $matches ) {
606
  return base64_decode( $matches[1] );
607
  },
612
  $this->content = $this->restore_noptimize( $this->content );
613
  //Restore the full content
614
  if ( ! empty( $this->restofcontent ) ) {
615
+ $this->content .= $this->restofcontent;
616
  $this->restofcontent = '';
617
  }
618
  // Inject the new stylesheets
inc/minification/breeze-minify-main.php CHANGED
@@ -1,382 +1,390 @@
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_Minify {
24
-
25
- public function __construct() {
26
- //check disable cache for page
27
- $domain = ( ( ( ! empty( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] !== 'off' ) || ( ! empty( $_SERVER['SERVER_PORT'] ) && $_SERVER['SERVER_PORT'] == 443 ) ) ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'];
28
- $current_url = $domain . $_SERVER['REQUEST_URI'];
29
-
30
- $check_url = $this->check_exclude_url( $current_url );
31
-
32
- //load config file when redirect template
33
- if ( ! $check_url && self::should_cache() ) {
34
- //cache html
35
- //cache minification
36
- if ( Breeze_MinificationCache::create_cache_minification_folder() ) {
37
- $conf = breeze_get_option( 'basic_settings' );
38
- $config_advanced = breeze_get_option( 'advanced_settings' );
39
- if ( ! empty( $conf['breeze-minify-html'] ) || ! empty( $conf['breeze-minify-css'] ) || ! empty( $conf['breeze-minify-js'] ) || ! empty( $config_advanced['breeze-defer-js'] ) ) {
40
-
41
- if ( defined( 'breeze_INIT_EARLIER' ) ) {
42
- add_action( 'init', array( $this, 'breeze_start_buffering' ), - 1 );
43
- } else {
44
- add_action( 'wp_loaded', array( $this, 'breeze_start_buffering' ), 2 );
45
- }
46
- }
47
- }
48
- }
49
-
50
- }
51
-
52
- /**
53
- * Check whether to execute caching functions or not.
54
- * Will not execute for purge cache or heartbeat actions.
55
- */
56
- public static function should_cache() {
57
- if ( isset( $_GET['breeze_purge'] ) || ( isset( $_POST['action'] ) && 'heartbeat' === $_POST['action'] ) ) {
58
- return false;
59
- }
60
-
61
- return true;
62
- }
63
-
64
- /*
65
- * Start buffer
66
- */
67
- public function breeze_start_buffering() {
68
- $ao_noptimize = false;
69
-
70
- // check for DONOTMINIFY constant as used by e.g. WooCommerce POS
71
- if ( defined( 'DONOTMINIFY' ) && ( constant( 'DONOTMINIFY' ) === true || constant( 'DONOTMINIFY' ) === "true" ) ) {
72
- $ao_noptimize = true;
73
- }
74
- // filter you can use to block autoptimization on your own terms
75
- $ao_noptimize = (bool) apply_filters( 'breeze_filter_noptimize', $ao_noptimize );
76
- if ( ! is_feed() && ! $ao_noptimize && ! is_admin() ) {
77
- // Config element
78
- $conf = breeze_get_option( 'basic_settings' );
79
- $config_advanced = breeze_get_option( 'advanced_settings' );
80
-
81
- // Load our base class
82
- include_once( BREEZE_PLUGIN_DIR . 'inc/minification/breeze-minification-base.php' );
83
-
84
- // Load extra classes and set some vars
85
- if ( ! empty( $conf['breeze-minify-html'] ) ) {
86
- include_once( BREEZE_PLUGIN_DIR . 'inc/minification/breeze-minification-html.php' );
87
- // BUG: new minify-html does not support keeping HTML comments, skipping for now
88
- if ( ! class_exists( 'Minify_HTML' ) ) {
89
- @include( BREEZE_PLUGIN_DIR . 'inc/minification/minify/minify-html.php' );
90
- }
91
- }
92
-
93
-
94
- if ( ! empty( $conf['breeze-minify-js'] ) ) {
95
-
96
- include_once( BREEZE_PLUGIN_DIR . 'inc/minification/breeze-minification-scripts.php' );
97
-
98
- // JS/CSS minifier library
99
- include_once( BREEZE_PLUGIN_DIR . 'vendor/autoload.php' );
100
-
101
- if ( ! defined( 'CONCATENATE_SCRIPTS' ) ) {
102
- define( 'CONCATENATE_SCRIPTS', false );
103
- }
104
- if ( ! defined( 'COMPRESS_SCRIPTS' ) ) {
105
- define( 'COMPRESS_SCRIPTS', false );
106
- }
107
- } elseif ( ! empty( $config_advanced['breeze-defer-js'] ) ) {
108
- // If we have defer scripts to handle, load only the script for this action.
109
- include_once( BREEZE_PLUGIN_DIR . 'inc/minification/breeze-js-deferred-loading.php' );
110
- }
111
-
112
- if ( ! empty( $conf['breeze-minify-css'] ) ) {
113
- include_once( BREEZE_PLUGIN_DIR . 'inc/minification/breeze-minification-styles.php' );
114
- if ( defined( 'breeze_LEGACY_MINIFIERS' ) ) {
115
- if ( ! class_exists( 'Minify_CSS_Compressor' ) ) {
116
- @include( BREEZE_PLUGIN_DIR . 'inc/minification/minify/minify-css-compressor.php' );
117
- }
118
- } else {
119
- if ( ! class_exists( 'CSSmin' ) ) {
120
- @include( BREEZE_PLUGIN_DIR . 'inc/minification/minify/yui-php-cssmin-2.4.8-4_fgo.php' );
121
- }
122
- }
123
- if ( ! defined( 'COMPRESS_CSS' ) ) {
124
- define( 'COMPRESS_CSS', false );
125
- }
126
- }
127
- // Now, start the real thing!
128
- add_filter( 'breeze_minify_content_return', array( $this, 'breeze_end_buffering' ) );
129
- }
130
- }
131
-
132
- /*
133
- * Minify css , js and optimize html when start
134
- */
135
-
136
- public function breeze_end_buffering( $content ) {
137
-
138
- if ( stripos( $content, "<html" ) === false || stripos( $content, "<html amp" ) !== false || stripos( $content, "<html ⚡" ) !== false || stripos( $content, "<xsl:stylesheet" ) !== false ) {
139
- return $content;
140
- }
141
- // load URL constants as late as possible to allow domain mapper to kick in
142
- if ( function_exists( "domain_mapping_siteurl" ) ) {
143
- define( 'breeze_WP_SITE_URL', domain_mapping_siteurl( get_current_blog_id() ) );
144
- define( 'breeze_WP_CONTENT_URL', str_replace( get_original_url( breeze_WP_SITE_URL ), breeze_WP_SITE_URL, content_url() ) );
145
- } else {
146
- define( 'breeze_WP_SITE_URL', site_url() );
147
- define( 'breeze_WP_CONTENT_URL', content_url() );
148
- }
149
- if ( is_multisite() && apply_filters( 'breeze_separate_blog_caches', true ) ) {
150
- $blog_id = get_current_blog_id();
151
- define( 'breeze_CACHE_URL', breeze_WP_CONTENT_URL . BREEZE_CACHE_CHILD_DIR . $blog_id . '/' );
152
- } else {
153
- define( 'breeze_CACHE_URL', breeze_WP_CONTENT_URL . BREEZE_CACHE_CHILD_DIR );
154
- }
155
- define( 'breeze_WP_ROOT_URL', str_replace( BREEZE_WP_CONTENT_NAME, '', breeze_WP_CONTENT_URL ) );
156
-
157
- define( 'breeze_HASH', wp_hash( breeze_CACHE_URL ) );
158
- // Config element
159
- $conf = breeze_get_option( 'basic_settings' );
160
- $minify = breeze_get_option( 'advanced_settings' );
161
-
162
- // Choose the classes
163
- $classes = array();
164
- $js_include_inline = $css_include_inline = false;
165
- if ( ! empty( $conf['breeze-minify-js'] ) ) {
166
- $classes[] = 'Breeze_MinificationScripts';
167
- } elseif ( ! empty( $minify['breeze-defer-js'] ) ) {
168
- $classes[] = 'Breeze_Js_Deferred_Loading';
169
- }
170
-
171
- if ( ! empty( $conf['breeze-minify-css'] ) ) {
172
- $classes[] = 'Breeze_MinificationStyles';
173
- }
174
- if ( ! empty( $conf['breeze-minify-html'] ) ) {
175
- $classes[] = 'Breeze_MinificationHtml';
176
- }
177
- if ( ! empty( $conf['breeze-include-inline-js'] ) ) {
178
- $js_include_inline = true;
179
- }
180
- if ( ! empty( $conf['breeze-include-inline-css'] ) ) {
181
- $css_include_inline = true;
182
- }
183
- $groupcss = false;
184
- $groupjs = false;
185
- if ( ! empty( $minify['breeze-group-css'] ) ) {
186
- $groupcss = true;
187
- }
188
- if ( ! empty( $minify['breeze-group-js'] ) ) {
189
- $groupjs = true;
190
- }
191
-
192
- // Set some options
193
- $classoptions = array(
194
- 'Breeze_MinificationScripts' => array(
195
- 'justhead' => false,
196
- 'forcehead' => false,
197
- 'trycatch' => false,
198
- 'js_exclude' => "s_sid, smowtion_size, sc_project, WAU_, wau_add, comment-form-quicktags, edToolbar, ch_client, seal.js",
199
- 'cdn_url' => "",
200
- 'include_inline' => $js_include_inline,
201
- 'group_js' => $groupjs,
202
- 'custom_js_exclude' => $minify['breeze-exclude-js'],
203
- 'move_to_footer_js' => $minify['breeze-move-to-footer-js'],
204
- 'defer_js' => $minify['breeze-defer-js']
205
- ),
206
- 'Breeze_MinificationStyles' => array(
207
- 'justhead' => false,
208
- 'datauris' => false,
209
- 'defer' => false,
210
- 'defer_inline' => false,
211
- 'inline' => false,
212
- 'css_exclude' => "admin-bar.min.css, dashicons.min.css",
213
- 'cdn_url' => "",
214
- 'include_inline' => $css_include_inline,
215
- 'nogooglefont' => false,
216
- 'groupcss' => $groupcss,
217
- 'custom_css_exclude' => $minify['breeze-exclude-css'],
218
- 'include_imported_css' => false,
219
- ),
220
- 'Breeze_MinificationHtml' => array(
221
- 'keepcomments' => false
222
- ),
223
- 'Breeze_Js_Deferred_Loading' => array(
224
- 'move_to_footer_js' => $minify['breeze-move-to-footer-js'],
225
- 'defer_js' => $minify['breeze-defer-js'],
226
- ),
227
- );
228
-
229
- $content = apply_filters( 'breeze_filter_html_before_minify', $content );
230
-
231
- if (
232
- ! empty( $conf ) &&
233
- $conf['breeze-disable-admin'] &&
234
- (
235
- current_user_can( 'administrator' ) ||
236
- current_user_can( 'editor' ) ||
237
- current_user_can( 'author' ) ||
238
- current_user_can( 'contributor' )
239
- )
240
- ) {
241
- $content = apply_filters( 'breeze_html_after_minify', $content );
242
-
243
- } else {
244
- // Run the classes
245
- foreach ( $classes as $name ) {
246
-
247
- $do_process = false;
248
- $instance = new $name( $content );
249
- if ( 'Breeze_MinificationStyles' === $name ) {
250
- $this_path_url = $instance->get_cache_file_url( 'css' );
251
- $do_process = breeze_is_process_locked( $this_path_url );
252
- }
253
-
254
- if ( 'Breeze_MinificationScripts' === $name ) {
255
- $this_path_url = $instance->get_cache_file_url( 'js' );
256
- $do_process = breeze_is_process_locked( $this_path_url );
257
- }
258
-
259
- if ( 'Breeze_MinificationHtml' === $name ) {
260
- $this_path_url = $instance->get_cache_file_url( '' );
261
- $do_process = breeze_is_process_locked( $this_path_url );
262
- }
263
-
264
- if ( false === $do_process ) {
265
-
266
- if ( $instance->read( $classoptions[ $name ] ) ) {
267
- $instance->minify();
268
- $instance->cache();
269
- $content = $instance->getcontent();
270
- }
271
- unset( $instance );
272
- }
273
-
274
- }
275
- $content = apply_filters( 'breeze_html_after_minify', $content );
276
- }
277
-
278
- return $content;
279
- }
280
-
281
- /*
282
- * Remove '/' chacracter of end url
283
- */
284
- public function rtrim_urls( $url ) {
285
- return rtrim( $url, '/' );
286
- }
287
-
288
- /*
289
- * check url from Never cache the following pages area
290
- */
291
- public function check_exclude_url( $current_url ) {
292
- $opts_config = breeze_get_option( 'advanced_settings' );
293
-
294
- $config_options = $this->read_the_config_file();
295
- if ( ! empty( $config_options ) ) {
296
- $opts_config['breeze-exclude-urls'] = array_merge( $opts_config['breeze-exclude-urls'], $config_options );
297
- $urls = array_unique( $opts_config['breeze-exclude-urls'] );
298
- $opts_config['breeze-exclude-urls'] = array_map( array( $this, 'rtrim_urls' ), $urls );
299
-
300
- }
301
-
302
- $is_exclude = breeze_check_for_exclude_values( $current_url, $opts_config['breeze-exclude-urls'] );
303
- if ( ! empty( $is_exclude ) ) {
304
- return true;
305
- }
306
-
307
- //check disable cache for page
308
- if ( ! empty( $opts_config['breeze-exclude-urls'] ) ) {
309
- foreach ( $opts_config['breeze-exclude-urls'] as $v ) {
310
- // Clear blank character
311
- $v = trim( $v );
312
- if ( preg_match( '/(\&?\/?\(\.?\*\)|\/\*|\*)$/', $v, $matches ) ) {
313
- // End of rules is *, /*, [&][/](*) , [&][/](.*)
314
- $pattent = substr( $v, 0, strpos( $v, $matches[0] ) );
315
- if ( $v[0] == '/' ) {
316
- // A path of exclude url with regex
317
- if ( ( @preg_match( '@' . $pattent . '@', $current_url, $matches ) > 0 ) ) {
318
- return true;
319
- }
320
- } else {
321
- // Full exclude url with regex
322
- if ( strpos( $current_url, $pattent ) !== false ) {
323
- return true;
324
- }
325
- }
326
-
327
- } else {
328
-
329
- $v = rtrim( $v, '/' );
330
- $current_url = rtrim( $current_url, '/' );
331
- $v = ltrim( $v, 'https:' );
332
- $current_url = ltrim( $current_url, 'https:' );
333
-
334
- // Whole path
335
- if ( $v == $current_url ) {
336
- return true;
337
- } else {
338
- $v = $str = strtok( $v, '?' );
339
- $current_url = $str = strtok( $current_url, '?' );
340
- $v = rtrim( $v, '/' );
341
- $current_url = rtrim( $current_url, '/' );
342
-
343
- if ( $v == $current_url ) {
344
- return true;
345
- }
346
- }
347
- }
348
- }
349
- }
350
-
351
- return false;
352
-
353
- }
354
-
355
- /*
356
- * Will Return the options for the current website
357
- *
358
- * @since 1.1.8
359
- * @access public
360
- */
361
- public function read_the_config_file() {
362
- $config_dir = trailingslashit( WP_CONTENT_DIR ) . 'breeze-config';
363
- $filename = 'breeze-config';
364
- if ( is_multisite() && ! is_network_admin() ) {
365
- $filename .= '-' . get_current_blog_id();
366
- }
367
-
368
- $config_file = $config_dir . DIRECTORY_SEPARATOR . $filename . '.php';
369
-
370
- if ( file_exists( $config_file ) ) {
371
- $config = include $config_file;
372
- if ( empty( $config ) || ! isset( $config['exclude_url'] ) || empty( $config['exclude_url'] ) ) {
373
- return false;
374
- }
375
-
376
- return $config['exclude_url'];
377
- } else {
378
- return false;
379
- }
380
-
381
- }
382
- }
 
 
 
 
 
 
 
 
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_Minify {
24
+
25
+ public function __construct() {
26
+ //check disable cache for page
27
+ $domain = ( ( ( ! empty( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] !== 'off' ) || ( ! empty( $_SERVER['SERVER_PORT'] ) && $_SERVER['SERVER_PORT'] == 443 ) ) ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'];
28
+ $current_url = $domain . $_SERVER['REQUEST_URI'];
29
+
30
+ $check_url = $this->check_exclude_url( $current_url );
31
+
32
+ //load config file when redirect template
33
+ if ( ! $check_url && self::should_cache() ) {
34
+ //cache html
35
+ //cache minification
36
+ if ( Breeze_MinificationCache::create_cache_minification_folder() ) {
37
+ $conf = breeze_get_option( 'basic_settings' );
38
+ $config_advanced = breeze_get_option( 'advanced_settings' );
39
+ if ( ! empty( $conf['breeze-minify-html'] ) || ! empty( $conf['breeze-minify-css'] ) || ! empty( $conf['breeze-minify-js'] ) || ! empty( $config_advanced['breeze-defer-js'] ) || ! empty( $config_advanced['breeze-move-to-footer-js'] ) ) {
40
+
41
+ if ( defined( 'breeze_INIT_EARLIER' ) ) {
42
+ add_action( 'init', array( $this, 'breeze_start_buffering' ), - 1 );
43
+ } else {
44
+ add_action( 'wp_loaded', array( $this, 'breeze_start_buffering' ), 2 );
45
+ }
46
+ }
47
+ }
48
+ }
49
+
50
+ }
51
+
52
+ /**
53
+ * Check whether to execute caching functions or not.
54
+ * Will not execute for purge cache or heartbeat actions.
55
+ */
56
+ public static function should_cache() {
57
+ if ( isset( $_GET['breeze_purge'] ) || ( isset( $_POST['action'] ) && 'heartbeat' === $_POST['action'] ) ) {
58
+ return false;
59
+ }
60
+
61
+ return true;
62
+ }
63
+
64
+ /*
65
+ * Start buffer
66
+ */
67
+ public function breeze_start_buffering() {
68
+ $ao_noptimize = false;
69
+
70
+ // check for DONOTMINIFY constant as used by e.g. WooCommerce POS
71
+ if ( defined( 'DONOTMINIFY' ) && ( constant( 'DONOTMINIFY' ) === true || constant( 'DONOTMINIFY' ) === 'true' ) ) {
72
+ $ao_noptimize = true;
73
+ }
74
+ // filter you can use to block autoptimization on your own terms
75
+ $ao_noptimize = (bool) apply_filters( 'breeze_filter_noptimize', $ao_noptimize );
76
+ if ( ! is_feed() && ! $ao_noptimize && ! is_admin() ) {
77
+ // Config element
78
+ $conf = breeze_get_option( 'basic_settings' );
79
+ $config_advanced = breeze_get_option( 'advanced_settings' );
80
+
81
+ // Load our base class
82
+ include_once( BREEZE_PLUGIN_DIR . 'inc/minification/breeze-minification-base.php' );
83
+
84
+ // Load extra classes and set some vars
85
+ if ( ! empty( $conf['breeze-minify-html'] ) ) {
86
+ include_once( BREEZE_PLUGIN_DIR . 'inc/minification/breeze-minification-html.php' );
87
+ // BUG: new minify-html does not support keeping HTML comments, skipping for now
88
+ if ( ! class_exists( 'Minify_HTML' ) ) {
89
+ @include( BREEZE_PLUGIN_DIR . 'inc/minification/minify/minify-html.php' );
90
+ }
91
+ }
92
+
93
+ if ( ! empty( $conf['breeze-minify-js'] ) ) {
94
+
95
+ include_once( BREEZE_PLUGIN_DIR . 'inc/minification/breeze-minification-scripts.php' );
96
+
97
+ // JS/CSS minifier library
98
+ include_once( BREEZE_PLUGIN_DIR . 'vendor/autoload.php' );
99
+
100
+ if ( ! defined( 'CONCATENATE_SCRIPTS' ) ) {
101
+ define( 'CONCATENATE_SCRIPTS', false );
102
+ }
103
+ if ( ! defined( 'COMPRESS_SCRIPTS' ) ) {
104
+ define( 'COMPRESS_SCRIPTS', false );
105
+ }
106
+ } elseif ( ! empty( $config_advanced['breeze-defer-js'] ) || ! empty( $config_advanced['breeze-move-to-footer-js'] ) ) {
107
+ // If we have defer scripts to handle, load only the script for this action.
108
+ include_once( BREEZE_PLUGIN_DIR . 'inc/minification/breeze-js-deferred-loading.php' );
109
+ }
110
+
111
+ if ( ! empty( $conf['breeze-minify-css'] ) ) {
112
+ include_once( BREEZE_PLUGIN_DIR . 'inc/minification/breeze-minification-styles.php' );
113
+ if ( defined( 'breeze_LEGACY_MINIFIERS' ) ) {
114
+ if ( ! class_exists( 'Minify_CSS_Compressor' ) ) {
115
+ @include( BREEZE_PLUGIN_DIR . 'inc/minification/minify/minify-css-compressor.php' );
116
+ }
117
+ } else {
118
+ if ( ! class_exists( 'CSSmin' ) ) {
119
+ @include( BREEZE_PLUGIN_DIR . 'inc/minification/minify/yui-php-cssmin-2.4.8-4_fgo.php' );
120
+ }
121
+ }
122
+ if ( ! defined( 'COMPRESS_CSS' ) ) {
123
+ define( 'COMPRESS_CSS', false );
124
+ }
125
+ }
126
+ // Now, start the real thing!
127
+ add_filter( 'breeze_minify_content_return', array( $this, 'breeze_end_buffering' ) );
128
+ }
129
+ }
130
+
131
+ /*
132
+ * Minify css , js and optimize html when start
133
+ */
134
+
135
+ public function breeze_end_buffering( $content ) {
136
+
137
+ if ( stripos( $content, '<html' ) === false || stripos( $content, '<html amp' ) !== false || stripos( $content, '<html ⚡' ) !== false || stripos( $content, '<xsl:stylesheet' ) !== false ) {
138
+ return $content;
139
+ }
140
+ // load URL constants as late as possible to allow domain mapper to kick in
141
+ if ( function_exists( 'domain_mapping_siteurl' ) ) {
142
+ define( 'breeze_WP_SITE_URL', domain_mapping_siteurl( get_current_blog_id() ) );
143
+ define( 'breeze_WP_CONTENT_URL', str_replace( get_original_url( breeze_WP_SITE_URL ), breeze_WP_SITE_URL, content_url() ) );
144
+ } else {
145
+ define( 'breeze_WP_SITE_URL', site_url() );
146
+ define( 'breeze_WP_CONTENT_URL', content_url() );
147
+ }
148
+ if ( is_multisite() && apply_filters( 'breeze_separate_blog_caches', true ) ) {
149
+ $blog_id = get_current_blog_id();
150
+ define( 'breeze_CACHE_URL', breeze_WP_CONTENT_URL . BREEZE_CACHE_CHILD_DIR . $blog_id . '/' );
151
+ } else {
152
+ define( 'breeze_CACHE_URL', breeze_WP_CONTENT_URL . BREEZE_CACHE_CHILD_DIR );
153
+ }
154
+ define( 'breeze_WP_ROOT_URL', str_replace( BREEZE_WP_CONTENT_NAME, '', breeze_WP_CONTENT_URL ) );
155
+
156
+ define( 'breeze_HASH', wp_hash( breeze_CACHE_URL ) );
157
+ // Config element
158
+ $conf = breeze_get_option( 'basic_settings' );
159
+ $minify = breeze_get_option( 'advanced_settings' );
160
+ $cdn_data = breeze_get_option( 'cdn_integration' );
161
+ $cdn_url = '';
162
+ if ( $cdn_data ) {
163
+ if ( '1' === $cdn_data['cdn-active'] ) {
164
+ $cdn_url = $cdn_data['cdn-url'];
165
+ }
166
+ }
167
+ // Choose the classes
168
+ $classes = array();
169
+ $js_include_inline = $css_include_inline = false;
170
+ if ( ! empty( $conf['breeze-minify-js'] ) ) {
171
+ $classes[] = 'Breeze_MinificationScripts';
172
+ } elseif ( ! empty( $minify['breeze-defer-js'] ) || ! empty( $minify['breeze-move-to-footer-js'] ) ) {
173
+ $classes[] = 'Breeze_Js_Deferred_Loading';
174
+ }
175
+
176
+ if ( ! empty( $conf['breeze-minify-css'] ) ) {
177
+ $classes[] = 'Breeze_MinificationStyles';
178
+ }
179
+ if ( ! empty( $conf['breeze-minify-html'] ) ) {
180
+ $classes[] = 'Breeze_MinificationHtml';
181
+ }
182
+ if ( ! empty( $conf['breeze-include-inline-js'] ) ) {
183
+ $js_include_inline = true;
184
+ }
185
+ if ( ! empty( $conf['breeze-include-inline-css'] ) ) {
186
+ $css_include_inline = true;
187
+ }
188
+ $groupcss = false;
189
+ $groupjs = false;
190
+ if ( ! empty( $minify['breeze-group-css'] ) ) {
191
+ $groupcss = true;
192
+ }
193
+ if ( ! empty( $minify['breeze-group-js'] ) ) {
194
+ $groupjs = true;
195
+ }
196
+
197
+ // Set some options
198
+ $classoptions = array(
199
+ 'Breeze_MinificationScripts' => array(
200
+ 'justhead' => false,
201
+ 'forcehead' => false,
202
+ 'trycatch' => false,
203
+ 'js_exclude' => 's_sid, smowtion_size, sc_project, WAU_, wau_add, comment-form-quicktags, edToolbar, ch_client, seal.js',
204
+ 'cdn_url' => '',
205
+ 'include_inline' => $js_include_inline,
206
+ 'group_js' => $groupjs,
207
+ 'custom_js_exclude' => $minify['breeze-exclude-js'],
208
+ 'move_to_footer_js' => $minify['breeze-move-to-footer-js'],
209
+ 'defer_js' => $minify['breeze-defer-js'],
210
+ ),
211
+ 'Breeze_MinificationStyles' => array(
212
+ 'justhead' => false,
213
+ 'datauris' => false,
214
+ 'defer' => false,
215
+ 'defer_inline' => false,
216
+ 'inline' => false,
217
+ 'css_exclude' => 'admin-bar.min.css, dashicons.min.css',
218
+ 'cdn_url' => '',
219
+ 'include_inline' => $css_include_inline,
220
+ 'nogooglefont' => false,
221
+ 'groupcss' => $groupcss,
222
+ 'custom_css_exclude' => $minify['breeze-exclude-css'],
223
+ 'include_imported_css' => false,
224
+ ),
225
+ 'Breeze_MinificationHtml' => array(
226
+ 'keepcomments' => false,
227
+ ),
228
+ 'Breeze_Js_Deferred_Loading' => array(
229
+ 'move_to_footer_js' => $minify['breeze-move-to-footer-js'],
230
+ 'defer_js' => $minify['breeze-defer-js'],
231
+ 'cdn_url' => $cdn_url,
232
+ ),
233
+ );
234
+
235
+ $content = apply_filters( 'breeze_filter_html_before_minify', $content );
236
+
237
+ if ( ! empty( $conf ) && $conf['breeze-disable-admin'] && ( current_user_can( 'administrator' ) || current_user_can( 'editor' ) || current_user_can( 'author' ) || current_user_can( 'contributor' ) ) ) {
238
+ $content = apply_filters( 'breeze_html_after_minify', $content );
239
+
240
+ } else {
241
+ // Run the classes
242
+ foreach ( $classes as $name ) {
243
+
244
+ $do_process = false;
245
+ $instance = new $name( $content );
246
+ if ( 'Breeze_MinificationStyles' === $name ) {
247
+ $this_path_url = $instance->get_cache_file_url( 'css' );
248
+ $do_process = breeze_is_process_locked( $this_path_url );
249
+ }
250
+
251
+ if ( 'Breeze_MinificationScripts' === $name ) {
252
+ $this_path_url = $instance->get_cache_file_url( 'js' );
253
+ $do_process = breeze_is_process_locked( $this_path_url );
254
+ }
255
+
256
+ if ( 'Breeze_MinificationHtml' === $name ) {
257
+ $this_path_url = $instance->get_cache_file_url( '' );
258
+ $do_process = breeze_is_process_locked( $this_path_url );
259
+ }
260
+
261
+ if ( false === $do_process ) {
262
+
263
+ if ( $instance->read( $classoptions[ $name ] ) ) {
264
+ $instance->minify();
265
+ $instance->cache();
266
+ $content = $instance->getcontent();
267
+ }
268
+ unset( $instance );
269
+ }
270
+ }
271
+ $content = apply_filters( 'breeze_html_after_minify', $content );
272
+ }
273
+
274
+ return $content;
275
+ }
276
+
277
+ /*
278
+ * Remove '/' chacracter of end url
279
+ */
280
+ public function rtrim_urls( $url ) {
281
+ return rtrim( $url, '/' );
282
+ }
283
+
284
+ /*
285
+ * check url from Never cache the following pages area
286
+ */
287
+ public function check_exclude_url( $current_url ) {
288
+ $opts_config = breeze_get_option( 'advanced_settings' );
289
+
290
+ $config_options = $this->read_the_config_file();
291
+ if ( ! empty( $config_options ) ) {
292
+
293
+ if ( empty( $opts_config ) || ! is_array( $opts_config ) ) {
294
+ $opts_config = array();
295
+ }
296
+
297
+ if ( ! isset( $opts_config['breeze-exclude-urls'] ) || ! is_array( $opts_config['breeze-exclude-urls'] ) ) {
298
+ $opts_config['breeze-exclude-urls'] = array();
299
+ }
300
+
301
+ $opts_config['breeze-exclude-urls'] = array_merge( $opts_config['breeze-exclude-urls'], $config_options );
302
+ $urls = array_unique( $opts_config['breeze-exclude-urls'] );
303
+ $opts_config['breeze-exclude-urls'] = array_map( array( $this, 'rtrim_urls' ), $urls );
304
+ }
305
+
306
+ $is_exclude = breeze_check_for_exclude_values( $current_url, $opts_config['breeze-exclude-urls'] );
307
+ if ( ! empty( $is_exclude ) ) {
308
+
309
+ return true;
310
+ }
311
+ //check disable cache for page
312
+ if ( ! empty( $opts_config['breeze-exclude-urls'] ) ) {
313
+ foreach ( $opts_config['breeze-exclude-urls'] as $v ) {
314
+ // Clear blank character
315
+ $v = trim( $v );
316
+ if ( preg_match( '/(\&?\/?\(\.?\*\)|\/\*|\*)$/', $v, $matches ) ) {
317
+ // End of rules is *, /*, [&][/](*) , [&][/](.*)
318
+ $pattent = substr( $v, 0, strpos( $v, $matches[0] ) );
319
+ if ( $v[0] == '/' ) {
320
+ // A path of exclude url with regex
321
+ if ( ( @preg_match( '@' . $pattent . '@', $current_url, $matches ) > 0 ) ) {
322
+ return true;
323
+ }
324
+ } else {
325
+ // Full exclude url with regex
326
+ if ( strpos( $current_url, $pattent ) !== false ) {
327
+ return true;
328
+ }
329
+ }
330
+ } else {
331
+
332
+ $test_url = rtrim( $v, '/' );
333
+ $current_url = rtrim( $current_url, '/' );
334
+ $test_url = ltrim( $test_url, 'https:' );
335
+ $current_url = ltrim( $current_url, 'https:' );
336
+
337
+ // Whole path
338
+ if ( $test_url == $current_url ) {
339
+ return true;
340
+ } else {
341
+ $test_url = $str = strtok( $test_url, '?' );
342
+ $test_url = rtrim( $test_url, '/' );
343
+
344
+ $current_url = $str = strtok( $current_url, '?' );
345
+ $current_url = rtrim( $current_url, '/' );
346
+
347
+ if ( $test_url == $current_url ) {
348
+ return true;
349
+ }
350
+ }
351
+ }
352
+ }
353
+ }
354
+
355
+ return false;
356
+
357
+ }
358
+
359
+ /*
360
+ * Will Return the options for the current website
361
+ *
362
+ * @since 1.1.8
363
+ * @access public
364
+ */
365
+ public function read_the_config_file() {
366
+ $config_dir = trailingslashit( WP_CONTENT_DIR ) . 'breeze-config';
367
+ $filename = 'breeze-config';
368
+ if ( is_multisite() && ! is_network_admin() ) {
369
+
370
+ $blog_id_requested = isset( $GLOBALS['breeze_config']['blog_id'] ) ? $GLOBALS['breeze_config']['blog_id'] : 0;
371
+ if ( empty( $blog_id_requested ) ) {
372
+ $blog_id_requested = get_current_blog_id();
373
+ }
374
+ $filename .= '-' . $blog_id_requested;
375
+ }
376
+
377
+ $config_file = $config_dir . DIRECTORY_SEPARATOR . $filename . '.php';
378
+ if ( file_exists( $config_file ) ) {
379
+ $config = include $config_file;
380
+ if ( empty( $config ) || ! isset( $config['exclude_url'] ) || empty( $config['exclude_url'] ) ) {
381
+ return false;
382
+ }
383
+
384
+ return $config['exclude_url'];
385
+ } else {
386
+ return false;
387
+ }
388
+
389
+ }
390
+ }
inc/minification/config/default.php CHANGED
@@ -1,64 +1,67 @@
1
- <?php exit;
2
-
3
- //Check everything exists before using it
4
- if(!isset($_SERVER['HTTP_ACCEPT_ENCODING']))
5
- $_SERVER['HTTP_ACCEPT_ENCODING'] = '';
6
- if(!isset($_SERVER['HTTP_USER_AGENT']))
7
- $_SERVER['HTTP_USER_AGENT'] = '';
8
-
9
- // Determine supported compression method
10
- $gzip = strstr($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip');
11
- $deflate = strstr($_SERVER['HTTP_ACCEPT_ENCODING'], 'deflate');
12
-
13
- // Determine used compression method
14
- $encoding = $gzip ? 'gzip' : ($deflate ? 'deflate' : 'none');
15
-
16
- // Check for buggy versions of Internet Explorer
17
- if (!strstr($_SERVER['HTTP_USER_AGENT'], 'Opera') &&
18
- preg_match('/^Mozilla\/4\.0 \(compatible; MSIE ([0-9]\.[0-9])/i', $_SERVER['HTTP_USER_AGENT'], $matches))
19
- {
20
- $version = floatval($matches[1]);
21
-
22
- if ($version < 6)
23
- $encoding = 'none';
24
-
25
- if ($version == 6 && !strstr($_SERVER['HTTP_USER_AGENT'], 'EV1'))
26
- $encoding = 'none';
27
- }
28
-
29
- //Some servers compress the output of PHP - Don't break in those cases
30
- if(ini_get('output_handler') == 'ob_gzhandler' || ini_get('zlib.output_compression') == 1)
31
- $encoding = 'none';
32
-
33
- //Get data
34
- $contents = file_get_contents(__FILE__.'.'.$encoding);
35
-
36
- // first check if we have to send 304
37
- $eTag=md5($contents);
38
- $modTime=filemtime(__FILE__.'.none');
39
-
40
- $eTagMatch = (isset($_SERVER['HTTP_IF_NONE_MATCH']) && strpos($_SERVER['HTTP_IF_NONE_MATCH'],$eTag));
41
- $modTimeMatch = (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) === $modTime);
42
-
43
- if (($modTimeMatch)||($eTagMatch)) {
44
- header('HTTP/1.1 304 Not Modified');
45
- header('Connection: close');
46
- } else {
47
- // send all sorts of headers
48
- $expireTime=60*60*24*356; // 1y max according to RFC
49
-
50
- if(isset($encoding) && $encoding != 'none')
51
- {
52
- header('Content-Encoding: '.$encoding);
53
- }
54
- header('Vary: Accept-Encoding');
55
- header('Content-Length: '.strlen($contents));
56
- header('Content-type: %%CONTENT%%; charset=utf-8');
57
- header('Cache-Control: max-age='.$expireTime.', public, must-revalidate');
58
- header('Expires: '.gmdate('D, d M Y H:i:s', time() + $expireTime).' GMT'); //10 years
59
- header('ETag: ' . $eTag);
60
- header('Last-Modified: '.gmdate('D, d M Y H:i:s', $modTime).' GMT');
61
-
62
- // send output
63
- echo $contents;
64
- }
 
 
 
1
+ <?php exit;
2
+
3
+ //Check everything exists before using it
4
+ if ( ! isset( $_SERVER['HTTP_ACCEPT_ENCODING'] ) ) {
5
+ $_SERVER['HTTP_ACCEPT_ENCODING'] = '';
6
+ }
7
+ if ( ! isset( $_SERVER['HTTP_USER_AGENT'] ) ) {
8
+ $_SERVER['HTTP_USER_AGENT'] = '';
9
+ }
10
+
11
+ // Determine supported compression method
12
+ $gzip = strstr( $_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip' );
13
+ $deflate = strstr( $_SERVER['HTTP_ACCEPT_ENCODING'], 'deflate' );
14
+
15
+ // Determine used compression method
16
+ $encoding = $gzip ? 'gzip' : ( $deflate ? 'deflate' : 'none' );
17
+
18
+ // Check for buggy versions of Internet Explorer
19
+ if ( ! strstr( $_SERVER['HTTP_USER_AGENT'], 'Opera' ) &&
20
+ preg_match( '/^Mozilla\/4\.0 \(compatible; MSIE ([0-9]\.[0-9])/i', $_SERVER['HTTP_USER_AGENT'], $matches ) ) {
21
+ $version = floatval( $matches[1] );
22
+
23
+ if ( $version < 6 ) {
24
+ $encoding = 'none';
25
+ }
26
+
27
+ if ( $version == 6 && ! strstr( $_SERVER['HTTP_USER_AGENT'], 'EV1' ) ) {
28
+ $encoding = 'none';
29
+ }
30
+ }
31
+
32
+ //Some servers compress the output of PHP - Don't break in those cases
33
+ if ( ini_get( 'output_handler' ) == 'ob_gzhandler' || ini_get( 'zlib.output_compression' ) == 1 ) {
34
+ $encoding = 'none';
35
+ }
36
+
37
+ //Get data
38
+ $contents = file_get_contents( __FILE__ . '.' . $encoding );
39
+
40
+ // first check if we have to send 304
41
+ $eTag = md5( $contents );
42
+ $modTime = filemtime( __FILE__ . '.none' );
43
+
44
+ $eTagMatch = ( isset( $_SERVER['HTTP_IF_NONE_MATCH'] ) && strpos( $_SERVER['HTTP_IF_NONE_MATCH'], $eTag ) );
45
+ $modTimeMatch = ( isset( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) && strtotime( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) === $modTime );
46
+
47
+ if ( ( $modTimeMatch ) || ( $eTagMatch ) ) {
48
+ header( 'HTTP/1.1 304 Not Modified' );
49
+ header( 'Connection: close' );
50
+ } else {
51
+ // send all sorts of headers
52
+ $expireTime = 60 * 60 * 24 * 356; // 1y max according to RFC
53
+
54
+ if ( isset( $encoding ) && $encoding != 'none' ) {
55
+ header( 'Content-Encoding: ' . $encoding );
56
+ }
57
+ header( 'Vary: Accept-Encoding' );
58
+ header( 'Content-Length: ' . strlen( $contents ) );
59
+ header( 'Content-type: %%CONTENT%%; charset=utf-8' );
60
+ header( 'Cache-Control: max-age=' . $expireTime . ', public, must-revalidate' );
61
+ header( 'Expires: ' . gmdate( 'D, d M Y H:i:s', time() + $expireTime ) . ' GMT' ); //10 years
62
+ header( 'ETag: ' . $eTag );
63
+ header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s', $modTime ) . ' GMT' );
64
+
65
+ // send output
66
+ echo $contents;
67
+ }
inc/minification/config/delayed.php CHANGED
@@ -1,85 +1,87 @@
1
- <?php exit;
2
-
3
- //Check everything exists before using it
4
- if(!isset($_SERVER['HTTP_ACCEPT_ENCODING']))
5
- $_SERVER['HTTP_ACCEPT_ENCODING'] = '';
6
- if(!isset($_SERVER['HTTP_USER_AGENT']))
7
- $_SERVER['HTTP_USER_AGENT'] = '';
8
-
9
- // Determine supported compression method
10
- $gzip = strstr($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip');
11
- $deflate = strstr($_SERVER['HTTP_ACCEPT_ENCODING'], 'deflate');
12
-
13
- // Determine used compression method
14
- $encoding = $gzip ? 'gzip' : ($deflate ? 'deflate' : 'none');
15
-
16
- // Check for buggy versions of Internet Explorer
17
- if (!strstr($_SERVER['HTTP_USER_AGENT'], 'Opera') &&
18
- preg_match('/^Mozilla\/4\.0 \(compatible; MSIE ([0-9]\.[0-9])/i', $_SERVER['HTTP_USER_AGENT'], $matches))
19
- {
20
- $version = floatval($matches[1]);
21
-
22
- if ($version < 6)
23
- $encoding = 'none';
24
-
25
- if ($version == 6 && !strstr($_SERVER['HTTP_USER_AGENT'], 'EV1'))
26
- $encoding = 'none';
27
- }
28
-
29
- //Some servers compress the output of PHP - Don't break in those cases
30
- if(ini_get('output_handler') == 'ob_gzhandler' || ini_get('zlib.output_compression') == 1)
31
- $encoding = 'none';
32
-
33
- $iscompressed = file_exists(__FILE__.'.'.$encoding);
34
- if($encoding != 'none' && $iscompressed == false)
35
- {
36
- $flag = ($encoding == 'gzip' ? FORCE_GZIP : FORCE_DEFLATE);
37
- $code = file_get_contents(__FILE__.'.none');
38
- $contents = gzencode($code,9,$flag);
39
- }else{
40
- //Get data
41
- $contents = file_get_contents(__FILE__.'.'.$encoding);
42
- }
43
-
44
- // first check if we have to send 304
45
- // inspired by http://www.jonasjohn.de/snippets/php/caching.htm
46
-
47
- $eTag=md5($contents);
48
- $modTime=filemtime(__FILE__.'.none');
49
-
50
- $eTagMatch = (isset($_SERVER['HTTP_IF_NONE_MATCH']) && strpos($_SERVER['HTTP_IF_NONE_MATCH'],$eTag));
51
- $modTimeMatch = (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) === $modTime);
52
-
53
- if (($modTimeMatch)||($eTagMatch)) {
54
- header('HTTP/1.1 304 Not Modified');
55
- header('Connection: close');
56
- } else {
57
- // send all sorts of headers
58
- $expireTime=60*60*24*355; // 1y max according to RFC
59
- if ($encoding != 'none') {
60
- header('Content-Encoding: '.$encoding);
61
- }
62
- header('Vary: Accept-Encoding');
63
- header('Content-Length: '.strlen($contents));
64
- header('Content-type: %%CONTENT%%; charset=utf-8');
65
- header('Cache-Control: max-age='.$expireTime.', public, must-revalidate');
66
- header('Expires: '.gmdate('D, d M Y H:i:s', time() + $expireTime).' GMT');
67
- header('ETag: ' . $eTag);
68
- header('Last-Modified: '.gmdate('D, d M Y H:i:s', $modTime).' GMT');
69
-
70
- // send output
71
- echo $contents;
72
-
73
- //And write to filesystem cache if not done yet
74
- if($encoding != 'none' && $iscompressed == false)
75
- {
76
- //Write the content we sent
77
- file_put_contents(__FILE__.'.'.$encoding,$contents);
78
-
79
- //And write the new content
80
- $flag = ($encoding == 'gzip' ? FORCE_DEFLATE : FORCE_GZIP);
81
- $ext = ($encoding == 'gzip' ? 'deflate' : 'gzip');
82
- $contents = gzencode($code,9,$flag);
83
- file_put_contents(__FILE__.'.'.$ext,$contents);
84
- }
85
- }
 
 
1
+ <?php exit;
2
+
3
+ //Check everything exists before using it
4
+ if ( ! isset( $_SERVER['HTTP_ACCEPT_ENCODING'] ) ) {
5
+ $_SERVER['HTTP_ACCEPT_ENCODING'] = '';
6
+ }
7
+ if ( ! isset( $_SERVER['HTTP_USER_AGENT'] ) ) {
8
+ $_SERVER['HTTP_USER_AGENT'] = '';
9
+ }
10
+
11
+ // Determine supported compression method
12
+ $gzip = strstr( $_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip' );
13
+ $deflate = strstr( $_SERVER['HTTP_ACCEPT_ENCODING'], 'deflate' );
14
+
15
+ // Determine used compression method
16
+ $encoding = $gzip ? 'gzip' : ( $deflate ? 'deflate' : 'none' );
17
+
18
+ // Check for buggy versions of Internet Explorer
19
+ if ( ! strstr( $_SERVER['HTTP_USER_AGENT'], 'Opera' ) &&
20
+ preg_match( '/^Mozilla\/4\.0 \(compatible; MSIE ([0-9]\.[0-9])/i', $_SERVER['HTTP_USER_AGENT'], $matches ) ) {
21
+ $version = floatval( $matches[1] );
22
+
23
+ if ( $version < 6 ) {
24
+ $encoding = 'none';
25
+ }
26
+
27
+ if ( $version == 6 && ! strstr( $_SERVER['HTTP_USER_AGENT'], 'EV1' ) ) {
28
+ $encoding = 'none';
29
+ }
30
+ }
31
+
32
+ //Some servers compress the output of PHP - Don't break in those cases
33
+ if ( ini_get( 'output_handler' ) == 'ob_gzhandler' || ini_get( 'zlib.output_compression' ) == 1 ) {
34
+ $encoding = 'none';
35
+ }
36
+
37
+ $iscompressed = file_exists( __FILE__ . '.' . $encoding );
38
+ if ( $encoding != 'none' && $iscompressed == false ) {
39
+ $flag = ( $encoding == 'gzip' ? FORCE_GZIP : FORCE_DEFLATE );
40
+ $code = file_get_contents( __FILE__ . '.none' );
41
+ $contents = gzencode( $code, 9, $flag );
42
+ } else {
43
+ //Get data
44
+ $contents = file_get_contents( __FILE__ . '.' . $encoding );
45
+ }
46
+
47
+ // first check if we have to send 304
48
+ // inspired by http://www.jonasjohn.de/snippets/php/caching.htm
49
+
50
+ $eTag = md5( $contents );
51
+ $modTime = filemtime( __FILE__ . '.none' );
52
+
53
+ $eTagMatch = ( isset( $_SERVER['HTTP_IF_NONE_MATCH'] ) && strpos( $_SERVER['HTTP_IF_NONE_MATCH'], $eTag ) );
54
+ $modTimeMatch = ( isset( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) && strtotime( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) === $modTime );
55
+
56
+ if ( ( $modTimeMatch ) || ( $eTagMatch ) ) {
57
+ header( 'HTTP/1.1 304 Not Modified' );
58
+ header( 'Connection: close' );
59
+ } else {
60
+ // send all sorts of headers
61
+ $expireTime = 60 * 60 * 24 * 355; // 1y max according to RFC
62
+ if ( $encoding != 'none' ) {
63
+ header( 'Content-Encoding: ' . $encoding );
64
+ }
65
+ header( 'Vary: Accept-Encoding' );
66
+ header( 'Content-Length: ' . strlen( $contents ) );
67
+ header( 'Content-type: %%CONTENT%%; charset=utf-8' );
68
+ header( 'Cache-Control: max-age=' . $expireTime . ', public, must-revalidate' );
69
+ header( 'Expires: ' . gmdate( 'D, d M Y H:i:s', time() + $expireTime ) . ' GMT' );
70
+ header( 'ETag: ' . $eTag );
71
+ header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s', $modTime ) . ' GMT' );
72
+
73
+ // send output
74
+ echo $contents;
75
+
76
+ //And write to filesystem cache if not done yet
77
+ if ( $encoding != 'none' && $iscompressed == false ) {
78
+ //Write the content we sent
79
+ file_put_contents( __FILE__ . '.' . $encoding, $contents );
80
+
81
+ //And write the new content
82
+ $flag = ( $encoding == 'gzip' ? FORCE_DEFLATE : FORCE_GZIP );
83
+ $ext = ( $encoding == 'gzip' ? 'deflate' : 'gzip' );
84
+ $contents = gzencode( $code, 9, $flag );
85
+ file_put_contents( __FILE__ . '.' . $ext, $contents );
86
+ }
87
+ }
inc/minification/config/minificationFontRegex.php CHANGED
@@ -1,8 +1,8 @@
1
- <?php
2
- // regex to find fonts, externalised to avoid nasty errors for php<5.3
3
-
4
- $fonturl_regex = <<<'LOD'
5
- ~(?(DEFINE)(?<quoted_content>(["']) (?>[^"'\\]++ | \\{2} | \\. | (?!\g{-1})["'] )*+ \g{-1})(?<comment> /\* .*? \*/ ) (?<url_skip>(?: data: ) [^"'\s)}]*+ ) (?<other_content>(?> [^u}/"']++ | \g<quoted_content> | \g<comment> | \Bu | u(?!rl\s*+\() | /(?!\*) | \g<url_start> \g<url_skip> ["']?+ )++ ) (?<anchor> \G(?<!^) ["']?+ | @font-face \s*+ { ) (?<url_start> url\( \s*+ ["']?+ ) ) \g<comment> (*SKIP)(*FAIL) | \g<anchor> \g<other_content>?+ \g<url_start> \K ((?:(?:https?:)?(?://[[:alnum:]\-\.]+)(?::[0-9]+)?)?\/[^"'\s)}]*+) ~xs
6
- LOD;
7
-
8
- ?>
1
+ <?php
2
+ // regex to find fonts, externalised to avoid nasty errors for php<5.3
3
+
4
+ $fonturl_regex = <<<'LOD'
5
+ ~(?(DEFINE)(?<quoted_content>(["']) (?>[^"'\\]++ | \\{2} | \\. | (?!\g{-1})["'] )*+ \g{-1})(?<comment> /\* .*? \*/ ) (?<url_skip>(?: data: ) [^"'\s)}]*+ ) (?<other_content>(?> [^u}/"']++ | \g<quoted_content> | \g<comment> | \Bu | u(?!rl\s*+\() | /(?!\*) | \g<url_start> \g<url_skip> ["']?+ )++ ) (?<anchor> \G(?<!^) ["']?+ | @font-face \s*+ { ) (?<url_start> url\( \s*+ ["']?+ ) ) \g<comment> (*SKIP)(*FAIL) | \g<anchor> \g<other_content>?+ \g<url_start> \K ((?:(?:https?:)?(?://[[:alnum:]\-\.]+)(?::[0-9]+)?)?\/[^"'\s)}]*+) ~xs
6
+ LOD;
7
+
8
+
inc/minification/minify/minify-css-compressor.php CHANGED
@@ -1,250 +1,276 @@
1
- <?php
2
- /**
3
- * Class Minify_CSS_Compressor
4
- * @package Minify
5
- */
6
-
7
- /**
8
- * Compress CSS
9
- *
10
- * This is a heavy regex-based removal of whitespace, unnecessary
11
- * comments and tokens, and some CSS value minimization, where practical.
12
- * Many steps have been taken to avoid breaking comment-based hacks,
13
- * including the ie5/mac filter (and its inversion), but expect tricky
14
- * hacks involving comment tokens in 'content' value strings to break
15
- * minimization badly. A test suite is available.
16
- *
17
- * @package Minify
18
- * @author Stephen Clay <steve@mrclay.org>
19
- * @author http://code.google.com/u/1stvamp/ (Issue 64 patch)
20
- */
21
- class Minify_CSS_Compressor {
22
-
23
- /**
24
- * Minify a CSS string
25
- *
26
- * @param string $css
27
- *
28
- * @param array $options (currently ignored)
29
- *
30
- * @return string
31
- */
32
- public static function process($css, $options = array())
33
- {
34
- $obj = new Minify_CSS_Compressor($options);
35
- return $obj->_process($css);
36
- }
37
-
38
- /**
39
- * @var array options
40
- */
41
- protected $_options = null;
42
-
43
- /**
44
- * @var bool Are we "in" a hack?
45
- *
46
- * I.e. are some browsers targetted until the next comment?
47
- */
48
- protected $_inHack = false;
49
-
50
-
51
- /**
52
- * Constructor
53
- *
54
- * @param array $options (currently ignored)
55
- *
56
- * @return null
57
- */
58
- private function __construct($options) {
59
- $this->_options = $options;
60
- }
61
-
62
- /**
63
- * Minify a CSS string
64
- *
65
- * @param string $css
66
- *
67
- * @return string
68
- */
69
- protected function _process($css)
70
- {
71
- $css = str_replace("\r\n", "\n", $css);
72
-
73
- // preserve empty comment after '>'
74
- // http://www.webdevout.net/css-hacks#in_css-selectors
75
- $css = preg_replace('@>/\\*\\s*\\*/@', '>/*keep*/', $css);
76
-
77
- // preserve empty comment between property and value
78
- // http://css-discuss.incutio.com/?page=BoxModelHack
79
- $css = preg_replace('@/\\*\\s*\\*/\\s*:@', '/*keep*/:', $css);
80
- $css = preg_replace('@:\\s*/\\*\\s*\\*/@', ':/*keep*/', $css);
81
-
82
- // apply callback to all valid comments (and strip out surrounding ws
83
- $css = preg_replace_callback('@\\s*/\\*([\\s\\S]*?)\\*/\\s*@'
84
- ,array($this, '_commentCB'), $css);
85
-
86
- // remove ws around { } and last semicolon in declaration block
87
- $css = preg_replace('/\\s*{\\s*/', '{', $css);
88
- $css = preg_replace('/;?\\s*}\\s*/', '}', $css);
89
-
90
- // remove ws surrounding semicolons
91
- $css = preg_replace('/\\s*;\\s*/', ';', $css);
92
-
93
- // remove ws around urls
94
- $css = preg_replace('/
95
- url\\( # url(
96
- \\s*
97
- ([^\\)]+?) # 1 = the URL (really just a bunch of non right parenthesis)
98
- \\s*
99
- \\) # )
100
- /x', 'url($1)', $css);
101
-
102
- // remove ws between rules and colons
103
- $css = preg_replace('/
104
- \\s*
105
- ([{;]) # 1 = beginning of block or rule separator
106
- \\s*
107
- ([\\*_]?[\\w\\-]+) # 2 = property (and maybe IE filter)
108
- \\s*
109
- :
110
- \\s*
111
- (\\b|[#\'"]) # 3 = first character of a value
112
- /x', '$1$2:$3', $css);
113
-
114
- // remove ws in selectors
115
- $css = preg_replace_callback('/
116
- (?: # non-capture
117
- \\s*
118
- [^~>+,\\s]+ # selector part
119
- \\s*
120
- [,>+~] # combinators
121
- )+
122
- \\s*
123
- [^~>+,\\s]+ # selector part
124
- { # open declaration block
125
- /x'
126
- ,array($this, '_selectorsCB'), $css);
127
-
128
- // minimize hex colors
129
- $css = preg_replace('/([^=])#([a-f\\d])\\2([a-f\\d])\\3([a-f\\d])\\4([\\s;\\}])/i'
130
- , '$1#$2$3$4$5', $css);
131
-
132
- // remove spaces between font families
133
- $css = preg_replace_callback('/font-family:([^;}]+)([;}])/'
134
- ,array($this, '_fontFamilyCB'), $css);
135
-
136
- $css = preg_replace('/@import\\s+url/', '@import url', $css);
137
-
138
- // replace any ws involving newlines with a single newline
139
- $css = preg_replace('/[ \\t]*\\n+\\s*/', "\n", $css);
140
-
141
- // separate common descendent selectors w/ newlines (to limit line lengths)
142
- $css = preg_replace('/([\\w#\\.\\*]+)\\s+([\\w#\\.\\*]+){/', "$1\n$2{", $css);
143
-
144
- // Use newline after 1st numeric value (to limit line lengths).
145
- $css = preg_replace('/
146
- ((?:padding|margin|border|outline):\\d+(?:px|em)?) # 1 = prop : 1st numeric value
147
- \\s+
148
- /x'
149
- ,"$1\n", $css);
150
-
151
- // prevent triggering IE6 bug: http://www.crankygeek.com/ie6pebug/
152
- $css = preg_replace('/:first-l(etter|ine)\\{/', ':first-l$1 {', $css);
153
-
154
- return trim($css);
155
- }
156
-
157
- /**
158
- * Replace what looks like a set of selectors
159
- *
160
- * @param array $m regex matches
161
- *
162
- * @return string
163
- */
164
- protected function _selectorsCB($m)
165
- {
166
- // remove ws around the combinators
167
- return preg_replace('/\\s*([,>+~])\\s*/', '$1', $m[0]);
168
- }
169
-
170
- /**
171
- * Process a comment and return a replacement
172
- *
173
- * @param array $m regex matches
174
- *
175
- * @return string
176
- */
177
- protected function _commentCB($m)
178
- {
179
- $hasSurroundingWs = (trim($m[0]) !== $m[1]);
180
- $m = $m[1];
181
- // $m is the comment content w/o the surrounding tokens,
182
- // but the return value will replace the entire comment.
183
- if ($m === 'keep') {
184
- return '/**/';
185
- }
186
- if ($m === '" "') {
187
- // component of http://tantek.com/CSS/Examples/midpass.html
188
- return '/*" "*/';
189
- }
190
- if (preg_match('@";\\}\\s*\\}/\\*\\s+@', $m)) {
191
- // component of http://tantek.com/CSS/Examples/midpass.html
192
- return '/*";}}/* */';
193
- }
194
- if ($this->_inHack) {
195
- // inversion: feeding only to one browser
196
- if (preg_match('@
197
- ^/ # comment started like /*/
198
- \\s*
199
- (\\S[\\s\\S]+?) # has at least some non-ws content
200
- \\s*
201
- /\\* # ends like /*/ or /**/
202
- @x', $m, $n)) {
203
- // end hack mode after this comment, but preserve the hack and comment content
204
- $this->_inHack = false;
205
- return "/*/{$n[1]}/**/";
206
- }
207
- }
208
- if (substr($m, -1) === '\\') { // comment ends like \*/
209
- // begin hack mode and preserve hack
210
- $this->_inHack = true;
211
- return '/*\\*/';
212
- }
213
- if ($m !== '' && $m[0] === '/') { // comment looks like /*/ foo */
214
- // begin hack mode and preserve hack
215
- $this->_inHack = true;
216
- return '/*/*/';
217
- }
218
- if ($this->_inHack) {
219
- // a regular comment ends hack mode but should be preserved
220
- $this->_inHack = false;
221
- return '/**/';
222
- }
223
- // Issue 107: if there's any surrounding whitespace, it may be important, so
224
- // replace the comment with a single space
225
- return $hasSurroundingWs // remove all other comments
226
- ? ' '
227
- : '';
228
- }
229
-
230
- /**
231
- * Process a font-family listing and return a replacement
232
- *
233
- * @param array $m regex matches
234
- *
235
- * @return string
236
- */
237
- protected function _fontFamilyCB($m)
238
- {
239
- $m[1] = preg_replace('/
240
- \\s*
241
- (
242
- "[^"]+" # 1 = family in double qutoes
243
- |\'[^\']+\' # or 1 = family in single quotes
244
- |[\\w\\-]+ # or 1 = unquoted family
245
- )
246
- \\s*
247
- /x', '$1', $m[1]);
248
- return 'font-family:' . $m[1] . $m[2];
249
- }
250
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Class Minify_CSS_Compressor
4
+ * @package Minify
5
+ */
6
+
7
+ /**
8
+ * Compress CSS
9
+ *
10
+ * This is a heavy regex-based removal of whitespace, unnecessary
11
+ * comments and tokens, and some CSS value minimization, where practical.
12
+ * Many steps have been taken to avoid breaking comment-based hacks,
13
+ * including the ie5/mac filter (and its inversion), but expect tricky
14
+ * hacks involving comment tokens in 'content' value strings to break
15
+ * minimization badly. A test suite is available.
16
+ *
17
+ * @package Minify
18
+ * @author Stephen Clay <steve@mrclay.org>
19
+ * @author http://code.google.com/u/1stvamp/ (Issue 64 patch)
20
+ */
21
+ class Minify_CSS_Compressor {
22
+
23
+ /**
24
+ * Minify a CSS string
25
+ *
26
+ * @param string $css
27
+ *
28
+ * @param array $options (currently ignored)
29
+ *
30
+ * @return string
31
+ */
32
+ public static function process( $css, $options = array() ) {
33
+ $obj = new Minify_CSS_Compressor( $options );
34
+ return $obj->_process( $css );
35
+ }
36
+
37
+ /**
38
+ * @var array options
39
+ */
40
+ protected $_options = null;
41
+
42
+ /**
43
+ * @var bool Are we "in" a hack?
44
+ *
45
+ * I.e. are some browsers targetted until the next comment?
46
+ */
47
+ protected $_inHack = false;
48
+
49
+
50
+ /**
51
+ * Constructor
52
+ *
53
+ * @param array $options (currently ignored)
54
+ *
55
+ * @return null
56
+ */
57
+ private function __construct( $options ) {
58
+ $this->_options = $options;
59
+ }
60
+
61
+ /**
62
+ * Minify a CSS string
63
+ *
64
+ * @param string $css
65
+ *
66
+ * @return string
67
+ */
68
+ protected function _process( $css ) {
69
+ $css = str_replace( "\r\n", "\n", $css );
70
+
71
+ // preserve empty comment after '>'
72
+ // http://www.webdevout.net/css-hacks#in_css-selectors
73
+ $css = preg_replace( '@>/\\*\\s*\\*/@', '>/*keep*/', $css );
74
+
75
+ // preserve empty comment between property and value
76
+ // http://css-discuss.incutio.com/?page=BoxModelHack
77
+ $css = preg_replace( '@/\\*\\s*\\*/\\s*:@', '/*keep*/:', $css );
78
+ $css = preg_replace( '@:\\s*/\\*\\s*\\*/@', ':/*keep*/', $css );
79
+
80
+ // apply callback to all valid comments (and strip out surrounding ws
81
+ $css = preg_replace_callback(
82
+ '@\\s*/\\*([\\s\\S]*?)\\*/\\s*@',
83
+ array( $this, '_commentCB' ),
84
+ $css
85
+ );
86
+
87
+ // remove ws around { } and last semicolon in declaration block
88
+ $css = preg_replace( '/\\s*{\\s*/', '{', $css );
89
+ $css = preg_replace( '/;?\\s*}\\s*/', '}', $css );
90
+
91
+ // remove ws surrounding semicolons
92
+ $css = preg_replace( '/\\s*;\\s*/', ';', $css );
93
+
94
+ // remove ws around urls
95
+ $css = preg_replace(
96
+ '/
97
+ url\\( # url(
98
+ \\s*
99
+ ([^\\)]+?) # 1 = the URL (really just a bunch of non right parenthesis)
100
+ \\s*
101
+ \\) # )
102
+ /x',
103
+ 'url($1)',
104
+ $css
105
+ );
106
+
107
+ // remove ws between rules and colons
108
+ $css = preg_replace(
109
+ '/
110
+ \\s*
111
+ ([{;]) # 1 = beginning of block or rule separator
112
+ \\s*
113
+ ([\\*_]?[\\w\\-]+) # 2 = property (and maybe IE filter)
114
+ \\s*
115
+ :
116
+ \\s*
117
+ (\\b|[#\'"]) # 3 = first character of a value
118
+ /x',
119
+ '$1$2:$3',
120
+ $css
121
+ );
122
+
123
+ // remove ws in selectors
124
+ $css = preg_replace_callback(
125
+ '/
126
+ (?: # non-capture
127
+ \\s*
128
+ [^~>+,\\s]+ # selector part
129
+ \\s*
130
+ [,>+~] # combinators
131
+ )+
132
+ \\s*
133
+ [^~>+,\\s]+ # selector part
134
+ { # open declaration block
135
+ /x',
136
+ array( $this, '_selectorsCB' ),
137
+ $css
138
+ );
139
+
140
+ // minimize hex colors
141
+ $css = preg_replace(
142
+ '/([^=])#([a-f\\d])\\2([a-f\\d])\\3([a-f\\d])\\4([\\s;\\}])/i',
143
+ '$1#$2$3$4$5',
144
+ $css
145
+ );
146
+
147
+ // remove spaces between font families
148
+ $css = preg_replace_callback(
149
+ '/font-family:([^;}]+)([;}])/',
150
+ array( $this, '_fontFamilyCB' ),
151
+ $css
152
+ );
153
+
154
+ $css = preg_replace( '/@import\\s+url/', '@import url', $css );
155
+
156
+ // replace any ws involving newlines with a single newline
157
+ $css = preg_replace( '/[ \\t]*\\n+\\s*/', "\n", $css );
158
+
159
+ // separate common descendent selectors w/ newlines (to limit line lengths)
160
+ $css = preg_replace( '/([\\w#\\.\\*]+)\\s+([\\w#\\.\\*]+){/', "$1\n$2{", $css );
161
+
162
+ // Use newline after 1st numeric value (to limit line lengths).
163
+ $css = preg_replace(
164
+ '/
165
+ ((?:padding|margin|border|outline):\\d+(?:px|em)?) # 1 = prop : 1st numeric value
166
+ \\s+
167
+ /x',
168
+ "$1\n",
169
+ $css
170
+ );
171
+
172
+ // prevent triggering IE6 bug: http://www.crankygeek.com/ie6pebug/
173
+ $css = preg_replace( '/:first-l(etter|ine)\\{/', ':first-l$1 {', $css );
174
+
175
+ return trim( $css );
176
+ }
177
+
178
+ /**
179
+ * Replace what looks like a set of selectors
180
+ *
181
+ * @param array $m regex matches
182
+ *
183
+ * @return string
184
+ */
185
+ protected function _selectorsCB( $m ) {
186
+ // remove ws around the combinators
187
+ return preg_replace( '/\\s*([,>+~])\\s*/', '$1', $m[0] );
188
+ }
189
+
190
+ /**
191
+ * Process a comment and return a replacement
192
+ *
193
+ * @param array $m regex matches
194
+ *
195
+ * @return string
196
+ */
197
+ protected function _commentCB( $m ) {
198
+ $hasSurroundingWs = ( trim( $m[0] ) !== $m[1] );
199
+ $m = $m[1];
200
+ // $m is the comment content w/o the surrounding tokens,
201
+ // but the return value will replace the entire comment.
202
+ if ( $m === 'keep' ) {
203
+ return '/**/';
204
+ }
205
+ if ( $m === '" "' ) {
206
+ // component of http://tantek.com/CSS/Examples/midpass.html
207
+ return '/*" "*/';
208
+ }
209
+ if ( preg_match( '@";\\}\\s*\\}/\\*\\s+@', $m ) ) {
210
+ // component of http://tantek.com/CSS/Examples/midpass.html
211
+ return '/*";}}/* */';
212
+ }
213
+ if ( $this->_inHack ) {
214
+ // inversion: feeding only to one browser
215
+ if ( preg_match(
216
+ '@
217
+ ^/ # comment started like /*/
218
+ \\s*
219
+ (\\S[\\s\\S]+?) # has at least some non-ws content
220
+ \\s*
221
+ /\\* # ends like /*/ or /**/
222
+ @x',
223
+ $m,
224
+ $n
225
+ ) ) {
226
+ // end hack mode after this comment, but preserve the hack and comment content
227
+ $this->_inHack = false;
228
+ return "/*/{$n[1]}/**/";
229
+ }
230
+ }
231
+ if ( substr( $m, -1 ) === '\\' ) { // comment ends like \*/
232
+ // begin hack mode and preserve hack
233
+ $this->_inHack = true;
234
+ return '/*\\*/';
235
+ }
236
+ if ( $m !== '' && $m[0] === '/' ) { // comment looks like /*/ foo */
237
+ // begin hack mode and preserve hack
238
+ $this->_inHack = true;
239
+ return '/*/*/';
240
+ }
241
+ if ( $this->_inHack ) {
242
+ // a regular comment ends hack mode but should be preserved
243
+ $this->_inHack = false;
244
+ return '/**/';
245
+ }
246
+ // Issue 107: if there's any surrounding whitespace, it may be important, so
247
+ // replace the comment with a single space
248
+ return $hasSurroundingWs // remove all other comments
249
+ ? ' '
250
+ : '';
251
+ }
252
+
253
+ /**
254
+ * Process a font-family listing and return a replacement
255
+ *
256
+ * @param array $m regex matches
257
+ *
258
+ * @return string
259
+ */
260
+ protected function _fontFamilyCB( $m ) {
261
+ $m[1] = preg_replace(
262
+ '/
263
+ \\s*
264
+ (
265
+ "[^"]+" # 1 = family in double qutoes
266
+ |\'[^\']+\' # or 1 = family in single quotes
267
+ |[\\w\\-]+ # or 1 = unquoted family
268
+ )
269
+ \\s*
270
+ /x',
271
+ '$1',
272
+ $m[1]
273
+ );
274
+ return 'font-family:' . $m[1] . $m[2];
275
+ }
276
+ }
inc/minification/minify/minify-html.php CHANGED
@@ -1,268 +1,270 @@
1
- <?php
2
- /**
3
- * Class Minify_HTML
4
- * @package Minify
5
- */
6
-
7
- /**
8
- * Compress HTML
9
- *
10
- * This is a heavy regex-based removal of whitespace, unnecessary comments and
11
- * tokens. IE conditional comments are preserved. There are also options to have
12
- * STYLE and SCRIPT blocks compressed by callback functions.
13
- *
14
- * A test suite is available.
15
- *
16
- * @package Minify
17
- * @author Stephen Clay <steve@mrclay.org>
18
- */
19
- class Minify_HTML {
20
-
21
- /**
22
- * "Minify" an HTML page
23
- *
24
- * @param string $html
25
- *
26
- * @param array $options
27
- *
28
- * 'cssMinifier' : (optional) callback function to process content of STYLE
29
- * elements.
30
- *
31
- * 'jsMinifier' : (optional) callback function to process content of SCRIPT
32
- * elements. Note: the type attribute is ignored.
33
- *
34
- * 'xhtml' : (optional boolean) should content be treated as XHTML1.0? If
35
- * unset, minify will sniff for an XHTML doctype.
36
- *
37
- * 'keepComments' : (optional boolean) should the HTML comments be kept
38
- * in the HTML Code?
39
- *
40
- * @return string
41
- */
42
- public static function minify($html, $options = array()) {
43
- $min = new Minify_HTML($html, $options);
44
- return $min->process();
45
- }
46
-
47
-
48
- /**
49
- * Create a minifier object
50
- *
51
- * @param string $html
52
- *
53
- * @param array $options
54
- *
55
- * 'cssMinifier' : (optional) callback function to process content of STYLE
56
- * elements.
57
- *
58
- * 'jsMinifier' : (optional) callback function to process content of SCRIPT
59
- * elements. Note: the type attribute is ignored.
60
- *
61
- * 'xhtml' : (optional boolean) should content be treated as XHTML1.0? If
62
- * unset, minify will sniff for an XHTML doctype.
63
- *
64
- * 'xhtml' : (optional boolean) should content be treated as XHTML1.0? If
65
- * unset, minify will sniff for an XHTML doctype.
66
- *
67
- * @return null
68
- */
69
- public function __construct($html, $options = array())
70
- {
71
- $this->_html = str_replace("\r\n", "\n", trim($html));
72
- if (isset($options['xhtml'])) {
73
- $this->_isXhtml = (bool)$options['xhtml'];
74
- }
75
- if (isset($options['cssMinifier'])) {
76
- $this->_cssMinifier = $options['cssMinifier'];
77
- }
78
- if (isset($options['jsMinifier'])) {
79
- $this->_jsMinifier = $options['jsMinifier'];
80
- }
81
- if (isset($options['keepComments'])) {
82
- $this->_keepComments = $options['keepComments'];
83
- }
84
- }
85
-
86
-
87
- /**
88
- * Minify the markeup given in the constructor
89
- *
90
- * @return string
91
- */
92
- public function process()
93
- {
94
- if ($this->_isXhtml === null) {
95
- $this->_isXhtml = (false !== strpos($this->_html, '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML'));
96
- }
97
-
98
- $this->_replacementHash = 'MINIFYHTML' . md5($_SERVER['REQUEST_TIME']);
99
- $this->_placeholders = array();
100
-
101
- // replace SCRIPTs (and minify) with placeholders
102
- $this->_html = preg_replace_callback(
103
- '/(\\s*)(<script\\b[^>]*?>)([\\s\\S]*?)<\\/script>(\\s*)/i'
104
- ,array($this, '_removeScriptCB')
105
- ,$this->_html);
106
-
107
- // replace STYLEs (and minify) with placeholders
108
- $this->_html = preg_replace_callback(
109
- '/\\s*(<style\\b[^>]*?>)([\\s\\S]*?)<\\/style>\\s*/i'
110
- ,array($this, '_removeStyleCB')
111
- ,$this->_html);
112
-
113
- // remove HTML comments (not containing IE conditional comments).
114
- if ($this->_keepComments == false) {
115
- $this->_html = preg_replace_callback(
116
- '/<!--([\\s\\S]*?)-->/'
117
- ,array($this, '_commentCB')
118
- ,$this->_html);
119
- }
120
-
121
- // replace PREs with placeholders
122
- $this->_html = preg_replace_callback('/\\s*(<pre\\b[^>]*?>[\\s\\S]*?<\\/pre>)\\s*/i'
123
- ,array($this, '_removePreCB')
124
- ,$this->_html);
125
-
126
- // replace TEXTAREAs with placeholders
127
- $this->_html = preg_replace_callback(
128
- '/\\s*(<textarea\\b[^>]*?>[\\s\\S]*?<\\/textarea>)\\s*/i'
129
- ,array($this, '_removeTextareaCB')
130
- ,$this->_html);
131
-
132
- // replace data: URIs with placeholders
133
- $this->_html = preg_replace_callback(
134
- '/(=("|\')data:.*\\2)/Ui'
135
- ,array($this, '_removeDataURICB')
136
- ,$this->_html);
137
-
138
- // trim each line.
139
- // @todo take into account attribute values that span multiple lines.
140
- $this->_html = preg_replace('/^\\s+|\\s+$/m', '', $this->_html);
141
-
142
- // remove ws around block/undisplayed elements
143
- $this->_html = preg_replace('/\\s+(<\\/?(?:area|article|aside|base(?:font)?|blockquote|body'
144
- .'|canvas|caption|center|col(?:group)?|dd|dir|div|dl|dt|fieldset|figcaption|figure|footer|form'
145
- .'|frame(?:set)?|h[1-6]|head|header|hgroup|hr|html|legend|li|link|main|map|menu|meta|nav'
146
- .'|ol|opt(?:group|ion)|output|p|param|section|t(?:able|body|head|d|h||r|foot|itle)'
147
- .'|ul|video)\\b[^>]*>)/i', '$1', $this->_html);
148
-
149
- // remove ws outside of all elements
150
- $this->_html = preg_replace_callback(
151
- '/>([^<]+)</'
152
- ,array($this, '_outsideTagCB')
153
- ,$this->_html);
154
-
155
- // use newlines before 1st attribute in open tags (to limit line lengths)
156
- //$this->_html = preg_replace('/(<[a-z\\-]+)\\s+([^>]+>)/i', "$1\n$2", $this->_html);
157
-
158
- // fill placeholders
159
- $this->_html = str_replace(
160
- array_keys($this->_placeholders)
161
- ,array_values($this->_placeholders)
162
- ,$this->_html
163
- );
164
- return $this->_html;
165
- }
166
-
167
- protected function _commentCB($m)
168
- {
169
- return (0 === strpos($m[1], '[') || false !== strpos($m[1], '<!['))
170
- ? $m[0]
171
- : '';
172
- }
173
-
174
- protected function _reservePlace($content)
175
- {
176
- $placeholder = '%' . $this->_replacementHash . count($this->_placeholders) . '%';
177
- $this->_placeholders[$placeholder] = $content;
178
- return $placeholder;
179
- }
180
-
181
- protected $_isXhtml = null;
182
- protected $_replacementHash = null;
183
- protected $_placeholders = array();
184
- protected $_cssMinifier = null;
185
- protected $_jsMinifier = null;
186
- protected $_keepComments = false;
187
-
188
- protected function _outsideTagCB($m)
189
- {
190
- return '>' . preg_replace('/^\\s+|\\s+$/', ' ', $m[1]) . '<';
191
- }
192
-
193
- protected function _removePreCB($m)
194
- {
195
- return $this->_reservePlace($m[1]);
196
- }
197
-
198
- protected function _removeTextareaCB($m)
199
- {
200
- return $this->_reservePlace($m[1]);
201
- }
202
-
203
- protected function _removeDataURICB($m)
204
- {
205
- return $this->_reservePlace($m[1]);
206
- }
207
-
208
- protected function _removeStyleCB($m)
209
- {
210
- $openStyle = $m[1];
211
- $css = $m[2];
212
- // remove HTML comments
213
- $css = preg_replace('/(?:^\\s*<!--|-->\\s*$)/', '', $css);
214
-
215
- // remove CDATA section markers
216
- $css = $this->_removeCdata($css);
217
-
218
- // minify
219
- $minifier = $this->_cssMinifier
220
- ? $this->_cssMinifier
221
- : 'trim';
222
- $css = call_user_func($minifier, $css);
223
-
224
- return $this->_reservePlace($this->_needsCdata($css)
225
- ? "{$openStyle}/*<![CDATA[*/{$css}/*]]>*/</style>"
226
- : "{$openStyle}{$css}</style>"
227
- );
228
- }
229
-
230
- protected function _removeScriptCB($m)
231
- {
232
- $openScript = $m[2];
233
- $js = $m[3];
234
-
235
- // whitespace surrounding? preserve at least one space
236
- $ws1 = ($m[1] === '') ? '' : ' ';
237
- $ws2 = ($m[4] === '') ? '' : ' ';
238
-
239
- // remove HTML comments (and ending "//" if present)
240
- $js = preg_replace('/(?:^\\s*<!--\\s*|\\s*(?:\\/\\/)?\\s*-->\\s*$)/', '', $js);
241
-
242
- // remove CDATA section markers
243
- $js = $this->_removeCdata($js);
244
-
245
- // minify
246
- $minifier = $this->_jsMinifier
247
- ? $this->_jsMinifier
248
- : 'trim';
249
- $js = call_user_func($minifier, $js);
250
-
251
- return $this->_reservePlace($this->_needsCdata($js)
252
- ? "{$ws1}{$openScript}/*<![CDATA[*/{$js}/*]]>*/</script>{$ws2}"
253
- : "{$ws1}{$openScript}{$js}</script>{$ws2}"
254
- );
255
- }
256
-
257
- protected function _removeCdata($str)
258
- {
259
- return (false !== strpos($str, '<![CDATA['))
260
- ? str_replace(array('/*<![CDATA[*/','/*]]>*/','<![CDATA[', ']]>'), '', $str)
261
- : $str;
262
- }
263
-
264
- protected function _needsCdata($str)
265
- {
266
- return ($this->_isXhtml && preg_match('/(?:[<&]|\\-\\-|\\]\\]>)/', $str));
267
- }
268
- }
 
 
1
+ <?php
2
+ /**
3
+ * Class Minify_HTML
4
+ * @package Minify
5
+ */
6
+
7
+ /**
8
+ * Compress HTML
9
+ *
10
+ * This is a heavy regex-based removal of whitespace, unnecessary comments and
11
+ * tokens. IE conditional comments are preserved. There are also options to have
12
+ * STYLE and SCRIPT blocks compressed by callback functions.
13
+ *
14
+ * A test suite is available.
15
+ *
16
+ * @package Minify
17
+ * @author Stephen Clay <steve@mrclay.org>
18
+ */
19
+ class Minify_HTML {
20
+
21
+ /**
22
+ * "Minify" an HTML page
23
+ *
24
+ * @param string $html
25
+ *
26
+ * @param array $options
27
+ *
28
+ * 'cssMinifier' : (optional) callback function to process content of STYLE
29
+ * elements.
30
+ *
31
+ * 'jsMinifier' : (optional) callback function to process content of SCRIPT
32
+ * elements. Note: the type attribute is ignored.
33
+ *
34
+ * 'xhtml' : (optional boolean) should content be treated as XHTML1.0? If
35
+ * unset, minify will sniff for an XHTML doctype.
36
+ *
37
+ * 'keepComments' : (optional boolean) should the HTML comments be kept
38
+ * in the HTML Code?
39
+ *
40
+ * @return string
41
+ */
42
+ public static function minify( $html, $options = array() ) {
43
+ $min = new Minify_HTML( $html, $options );
44
+ return $min->process();
45
+ }
46
+
47
+
48
+ /**
49
+ * Create a minifier object
50
+ *
51
+ * @param string $html
52
+ *
53
+ * @param array $options
54
+ *
55
+ * 'cssMinifier' : (optional) callback function to process content of STYLE
56
+ * elements.
57
+ *
58
+ * 'jsMinifier' : (optional) callback function to process content of SCRIPT
59
+ * elements. Note: the type attribute is ignored.
60
+ *
61
+ * 'xhtml' : (optional boolean) should content be treated as XHTML1.0? If
62
+ * unset, minify will sniff for an XHTML doctype.
63
+ *
64
+ * 'xhtml' : (optional boolean) should content be treated as XHTML1.0? If
65
+ * unset, minify will sniff for an XHTML doctype.
66
+ *
67
+ * @return null
68
+ */
69
+ public function __construct( $html, $options = array() ) {
70
+ $this->_html = str_replace( "\r\n", "\n", trim( $html ) );
71
+ if ( isset( $options['xhtml'] ) ) {
72
+ $this->_isXhtml = (bool) $options['xhtml'];
73
+ }
74
+ if ( isset( $options['cssMinifier'] ) ) {
75
+ $this->_cssMinifier = $options['cssMinifier'];
76
+ }
77
+ if ( isset( $options['jsMinifier'] ) ) {
78
+ $this->_jsMinifier = $options['jsMinifier'];
79
+ }
80
+ if ( isset( $options['keepComments'] ) ) {
81
+ $this->_keepComments = $options['keepComments'];
82
+ }
83
+ }
84
+
85
+
86
+ /**
87
+ * Minify the markeup given in the constructor
88
+ *
89
+ * @return string
90
+ */
91
+ public function process() {
92
+ if ( $this->_isXhtml === null ) {
93
+ $this->_isXhtml = ( false !== strpos( $this->_html, '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML' ) );
94
+ }
95
+
96
+ $this->_replacementHash = 'MINIFYHTML' . md5( $_SERVER['REQUEST_TIME'] );
97
+ $this->_placeholders = array();
98
+
99
+ // replace SCRIPTs (and minify) with placeholders
100
+ $this->_html = preg_replace_callback(
101
+ '/(\\s*)(<script\\b[^>]*?>)([\\s\\S]*?)<\\/script>(\\s*)/i',
102
+ array( $this, '_removeScriptCB' ),
103
+ $this->_html
104
+ );
105
+
106
+ // replace STYLEs (and minify) with placeholders
107
+ $this->_html = preg_replace_callback(
108
+ '/\\s*(<style\\b[^>]*?>)([\\s\\S]*?)<\\/style>\\s*/i',
109
+ array( $this, '_removeStyleCB' ),
110
+ $this->_html
111
+ );
112
+
113
+ // remove HTML comments (not containing IE conditional comments).
114
+ if ( $this->_keepComments == false ) {
115
+ $this->_html = preg_replace_callback(
116
+ '/<!--([\\s\\S]*?)-->/',
117
+ array( $this, '_commentCB' ),
118
+ $this->_html
119
+ );
120
+ }
121
+
122
+ // replace PREs with placeholders
123
+ $this->_html = preg_replace_callback(
124
+ '/\\s*(<pre\\b[^>]*?>[\\s\\S]*?<\\/pre>)\\s*/i',
125
+ array( $this, '_removePreCB' ),
126
+ $this->_html
127
+ );
128
+
129
+ // replace TEXTAREAs with placeholders
130
+ $this->_html = preg_replace_callback(
131
+ '/\\s*(<textarea\\b[^>]*?>[\\s\\S]*?<\\/textarea>)\\s*/i',
132
+ array( $this, '_removeTextareaCB' ),
133
+ $this->_html
134
+ );
135
+
136
+ // replace data: URIs with placeholders
137
+ $this->_html = preg_replace_callback(
138
+ '/(=("|\')data:.*\\2)/Ui',
139
+ array( $this, '_removeDataURICB' ),
140
+ $this->_html
141
+ );
142
+
143
+ // trim each line.
144
+ // @todo take into account attribute values that span multiple lines.
145
+ $this->_html = preg_replace( '/^\\s+|\\s+$/m', '', $this->_html );
146
+
147
+ // remove ws around block/undisplayed elements
148
+ $this->_html = preg_replace(
149
+ '/\\s+(<\\/?(?:area|article|aside|base(?:font)?|blockquote|body'
150
+ . '|canvas|caption|center|col(?:group)?|dd|dir|div|dl|dt|fieldset|figcaption|figure|footer|form'
151
+ . '|frame(?:set)?|h[1-6]|head|header|hgroup|hr|html|legend|li|link|main|map|menu|meta|nav'
152
+ . '|ol|opt(?:group|ion)|output|p|param|section|t(?:able|body|head|d|h||r|foot|itle)'
153
+ . '|ul|video)\\b[^>]*>)/i',
154
+ '$1',
155
+ $this->_html
156
+ );
157
+
158
+ // remove ws outside of all elements
159
+ $this->_html = preg_replace_callback(
160
+ '/>([^<]+)</',
161
+ array( $this, '_outsideTagCB' ),
162
+ $this->_html
163
+ );
164
+
165
+ // use newlines before 1st attribute in open tags (to limit line lengths)
166
+ //$this->_html = preg_replace('/(<[a-z\\-]+)\\s+([^>]+>)/i', "$1\n$2", $this->_html);
167
+
168
+ // fill placeholders
169
+ $this->_html = str_replace(
170
+ array_keys( $this->_placeholders ),
171
+ array_values( $this->_placeholders ),
172
+ $this->_html
173
+ );
174
+ return $this->_html;
175
+ }
176
+
177
+ protected function _commentCB( $m ) {
178
+ return ( 0 === strpos( $m[1], '[' ) || false !== strpos( $m[1], '<![' ) )
179
+ ? $m[0]
180
+ : '';
181
+ }
182
+
183
+ protected function _reservePlace( $content ) {
184
+ $placeholder = '%' . $this->_replacementHash . count( $this->_placeholders ) . '%';
185
+ $this->_placeholders[ $placeholder ] = $content;
186
+ return $placeholder;
187
+ }
188
+
189
+ protected $_isXhtml = null;
190
+ protected $_replacementHash = null;
191
+ protected $_placeholders = array();
192
+ protected $_cssMinifier = null;
193
+ protected $_jsMinifier = null;
194
+ protected $_keepComments = false;
195
+
196
+ protected function _outsideTagCB( $m ) {
197
+ return '>' . preg_replace( '/^\\s+|\\s+$/', ' ', $m[1] ) . '<';
198
+ }
199
+
200
+ protected function _removePreCB( $m ) {
201
+ return $this->_reservePlace( $m[1] );
202
+ }
203
+
204
+ protected function _removeTextareaCB( $m ) {
205
+ return $this->_reservePlace( $m[1] );
206
+ }
207
+
208
+ protected function _removeDataURICB( $m ) {
209
+ return $this->_reservePlace( $m[1] );
210
+ }
211
+
212
+ protected function _removeStyleCB( $m ) {
213
+ $openStyle = $m[1];
214
+ $css = $m[2];
215
+ // remove HTML comments
216
+ $css = preg_replace( '/(?:^\\s*<!--|-->\\s*$)/', '', $css );
217
+
218
+ // remove CDATA section markers
219
+ $css = $this->_removeCdata( $css );
220
+
221
+ // minify
222
+ $minifier = $this->_cssMinifier
223
+ ? $this->_cssMinifier
224
+ : 'trim';
225
+ $css = call_user_func( $minifier, $css );
226
+
227
+ return $this->_reservePlace(
228
+ $this->_needsCdata( $css )
229
+ ? "{$openStyle}/*<![CDATA[*/{$css}/*]]>*/</style>"
230
+ : "{$openStyle}{$css}</style>"
231
+ );
232
+ }
233
+
234
+ protected function _removeScriptCB( $m ) {
235
+ $openScript = $m[2];
236
+ $js = $m[3];
237
+
238
+ // whitespace surrounding? preserve at least one space
239
+ $ws1 = ( $m[1] === '' ) ? '' : ' ';
240
+ $ws2 = ( $m[4] === '' ) ? '' : ' ';
241
+
242
+ // remove HTML comments (and ending "//" if present)
243
+ $js = preg_replace( '/(?:^\\s*<!--\\s*|\\s*(?:\\/\\/)?\\s*-->\\s*$)/', '', $js );
244
+
245
+ // remove CDATA section markers
246
+ $js = $this->_removeCdata( $js );
247
+
248
+ // minify
249
+ $minifier = $this->_jsMinifier
250
+ ? $this->_jsMinifier
251
+ : 'trim';
252
+ $js = call_user_func( $minifier, $js );
253
+
254
+ return $this->_reservePlace(
255
+ $this->_needsCdata( $js )
256
+ ? "{$ws1}{$openScript}/*<![CDATA[*/{$js}/*]]>*/</script>{$ws2}"
257
+ : "{$ws1}{$openScript}{$js}</script>{$ws2}"
258
+ );
259
+ }
260
+
261
+ protected function _removeCdata( $str ) {
262
+ return ( false !== strpos( $str, '<![CDATA[' ) )
263
+ ? str_replace( array( '/*<![CDATA[*/', '/*]]>*/', '<![CDATA[', ']]>' ), '', $str )
264
+ : $str;
265
+ }
266
+
267
+ protected function _needsCdata( $str ) {
268
+ return ( $this->_isXhtml && preg_match( '/(?:[<&]|\\-\\-|\\]\\]>)/', $str ) );
269
+ }
270
+ }
readme.txt CHANGED
@@ -3,7 +3,7 @@ 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.7
6
- Stable tag: 1.1.9
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
@@ -145,6 +145,16 @@ Using Gzip, Breeze compresses the request files, further reducing the size of th
145
 
146
  == Changelog ==
147
 
 
 
 
 
 
 
 
 
 
 
148
  = 1.1.9 =
149
 
150
  Add: Improved handling of minification for Query stirng based exclusion in Never Cache These URLs option.
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.7
6
+ Stable tag: 1.1.10
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.10 =
149
+
150
+ * Fix: Apply deferred loading at individual file.
151
+ * Fix: exclude feed url generated by plugin “Facebook for WooCommerce”.
152
+ * Fix: purge site cache in subfolder.
153
+ * Fix: Inventory stock now updated at the Cart page.
154
+ * Fix: Improved Support for the new version of the WooCommerce Booking Calendar plugin.
155
+ * Add: Compatible with EDD and cartflow plugins.
156
+ * Add: pages include shortcode has been exclude by Breeze.
157
+
158
  = 1.1.9 =
159
 
160
  Add: Improved handling of minification for Query stirng based exclusion in Never Cache These URLs option.
views/breeze-setting-views.php CHANGED
@@ -1,135 +1,135 @@
1
- <?php
2
-
3
- defined('ABSPATH') or die;
4
-
5
- $tabs = array(
6
- 'basic' => __('BASIC OPTIONS', 'breeze'),
7
- 'advanced' => __('ADVANCED OPTIONS', 'breeze'),
8
- 'database' => __('DATABASE', 'breeze'),
9
- 'cdn' => __('CDN', 'breeze'),
10
- 'varnish' => __('VARNISH', 'breeze'),
11
- 'faq' => __('FAQs', 'breeze'),
12
- );
13
-
14
- $global_tabs = array(
15
- 'faq',
16
- );
17
-
18
- ?>
19
- <?php if (isset($_REQUEST['database-cleanup']) && $_REQUEST['database-cleanup'] == 'success'): ?>
20
- <div id="message-save-settings" class="notice notice-success is-dismissible" style="margin: 10px 0px 10px 0;padding: 10px;"><strong><?php _e('Database cleanup successful', 'breeze'); ?></strong></div>
21
- <?php endif; ?>
22
- <!--save settings successfull message-->
23
- <?php if (isset($_REQUEST['save-settings']) && $_REQUEST['save-settings'] == 'success'): ?>
24
- <div id="message-save-settings" class="notice notice-success is-dismissible" style="margin: 10px 0px 10px 0;padding: 10px;"><strong><?php _e('Configuration settings saved', 'breeze'); ?></strong></div>
25
- <?php endif; ?>
26
- <div class="wrap breeze-main">
27
- <div class="breeze-header">
28
- <a href="https://www.cloudways.com" target="_blank">
29
- <div class="breeze-logo"></div>
30
- </a>
31
- </div>
32
-
33
- <h1 style="clear: both"></h1>
34
-
35
- <?php
36
-
37
- $show_tabs = true;
38
- $is_subsite = is_multisite() && get_current_screen()->base !== 'settings_page_breeze-network';
39
-
40
- if ( $is_subsite ) {
41
- // Show settings inherit option.
42
- $inherit_settings = get_option( 'breeze_inherit_settings', 1 );
43
- if ( 0 != $inherit_settings ) {
44
- $inherit_settings = 1;
45
- $show_tabs = false;
46
- }
47
- ?>
48
- <form id="breeze-inherit-settings-toggle" class="breeze-form" method="post" action="">
49
- <div class="radio-field<?php echo $inherit_settings == 1 ? ' active' : ''; ?>">
50
- <label>
51
- <input type="radio" id="inherit-settings" name="inherit-settings" value="1" <?php checked( $inherit_settings, 1 ); ?>>
52
- <strong><?php esc_html_e( 'Use Network Level Settings for this site', 'breeze' ); ?>:</strong>
53
- </label>
54
- <small><?php esc_html_e( 'This option allows the subsite to inherit all the cache settings from network. To modify/update the settings please go to network site.', 'breeze' ); ?></small>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  </div>
56
- <div class="radio-field<?php echo $inherit_settings == 0 ? ' active' : ''; ?>">
57
- <label>
58
- <input type="radio" id="inherit-settings" name="inherit-settings" value="0" <?php checked( $inherit_settings, 0 ); ?>>
59
- <strong><?php esc_html_e( 'Use Custom Settings for this site', 'breeze' ); ?>:</strong>
60
- </label>
61
- <small><?php esc_html_e( 'This option allows subsite to have different settings/configuration from the network level. Use this option only if you wish to have separate settings for this subsite.', 'breeze' ); ?></small>
62
  </div>
63
-
64
- <p class="disclaimer"><?php esc_html_e( 'To apply your changes, please click on the Save Changes button.', 'breeze' ); ?></p>
65
-
66
- <?php wp_nonce_field( 'breeze_inherit_settings', 'breeze_inherit_settings_nonce' ); ?>
67
- </form>
68
-
69
- <h1 style="clear: both"></h1>
70
- <?php
71
- }
72
- ?>
73
-
74
- <ul id="breeze-tabs" class="nav-tab-wrapper <?php echo ! $show_tabs ? 'tabs-hidden' : ''; ?>">
75
- <?php
76
- foreach ( $tabs as $key => $name ) {
77
- $is_inactive = ! $show_tabs && ! in_array( $key, $global_tabs );
78
- echo '<a id="tab-' . $key . '" class="nav-tab' . ( $is_inactive ? ' inactive' : '' ) . '" href="#tab-' . $key . '" data-tab-id="' . $key . '"> ' . $name . ' </a> ';
79
- }
80
- ?>
81
- </ul>
82
-
83
- <div id="breeze-tabs-content" class="tab-content <?php echo ! $show_tabs ? 'tabs-hidden' : ''; ?>">
84
- <?php
85
- foreach ( $tabs as $key => $name ) {
86
- $is_inactive = ! $show_tabs && ! in_array( $key, $global_tabs );
87
- echo '<div id="tab-content-' . $key . '" class="tab-pane' . ( $is_inactive ? ' inactive' : '' ) . '">';
88
- echo '<form class="breeze-form" method="post" action="">';
89
- echo '<div class="tab-child">';
90
- echo '<input type="hidden" name="breeze_'.$key.'_action" value="breeze_'.$key.'_settings">';
91
- wp_nonce_field('breeze_settings_' . $key, 'breeze_settings_' . $key . '_nonce');
92
- Breeze_Admin::render($key);
93
- echo '</div>';
94
-
95
- if (
96
- $key != 'faq' &&
97
- ( $key != 'database' || ( is_multisite() && ! is_network_admin() ) )
98
- ) {
99
- if ( is_multisite() && is_network_admin() ) {
100
- echo '<p class="multisite-inherit-disclaimer">' . __( '* Any change here will also be applied to all the sub-sites that are using Network level settings.', 'wpr' ) . '</p>';
101
- }
102
- echo '<p class="submit">' . PHP_EOL .
103
- '<input type="submit" class="button button-primary breeze-submit-btn" value="'. __('Save Changes', 'breeze') .'"/>' . PHP_EOL .
104
- '</p>';
105
- }
106
- if ( ! in_array( $key, $global_tabs ) ) {
107
- echo '<span class="hidden-text">' . esc_attr__( 'When Network Level Settings is selected, modifications/updates can only be done from the main Network site.', 'breeze' ) . '</span>';
108
- }
109
- echo '</form>';
110
- echo '</div>';
111
- }
112
- ?>
113
-
114
- <!--Right-side content-->
115
- <div id="breeze-and-cloudways" class="rs-block">
116
- <h3 class="rs-title"><?php _e('Want to Experience Better Performance?', 'breeze') ?></h3>
117
- <div class="rs-content">
118
- <p><?php _e('Take advantage of powerful features by deploying WordPress and Breeze on Cloudways.', 'breeze') ?></p>
119
- <ul>
120
- <li><?php _e('Fully Compatible with Varnish', 'breeze') ?></li>
121
- <li><?php _e('One-Click setup of CloudwaysCDN', 'breeze') ?></li>
122
- <li><?php _e('24/7 Expert Human Support', 'breeze') ?></li>
123
- <li><?php _e('WooCommerce Compatible', 'breeze') ?></li>
124
- </ul>
125
- <button class="button button-primary">
126
- <a href="https://www.cloudways.com/en/wordpress-cloud-hosting.php?utm_source=breeze-plugin&utm_medium=breeze&utm_campaign=breeze" target="_blank"><?php _e('Find Out More', 'breeze') ?></a>
127
- </button>
128
- </div>
129
- <div class="rs-content">
130
- <h4><?php _e('Rate Breeze', 'breeze') ?></h4>
131
- <p><?php _e('If you are satisfied with Breeze\'s performance, <a href="https://wordpress.org/plugins/breeze#reviews" target="_blank">drop us a rating here.</a>', 'breeze') ?></p>
132
- </div>
133
- </div>
134
- </div>
135
- </div>
1
+ <?php
2
+
3
+ defined( 'ABSPATH' ) or die;
4
+
5
+ $tabs = array(
6
+ 'basic' => __( 'BASIC OPTIONS', 'breeze' ),
7
+ 'advanced' => __( 'ADVANCED OPTIONS', 'breeze' ),
8
+ 'database' => __( 'DATABASE', 'breeze' ),
9
+ 'cdn' => __( 'CDN', 'breeze' ),
10
+ 'varnish' => __( 'VARNISH', 'breeze' ),
11
+ 'faq' => __( 'FAQs', 'breeze' ),
12
+ );
13
+
14
+ $global_tabs = array(
15
+ 'faq',
16
+ );
17
+
18
+ ?>
19
+ <?php if ( isset( $_REQUEST['database-cleanup'] ) && $_REQUEST['database-cleanup'] == 'success' ) : ?>
20
+ <div id="message-save-settings" class="notice notice-success is-dismissible" style="margin: 10px 0px 10px 0;padding: 10px;"><strong><?php _e( 'Database cleanup successful', 'breeze' ); ?></strong></div>
21
+ <?php endif; ?>
22
+ <!--save settings successfull message-->
23
+ <?php if ( isset( $_REQUEST['save-settings'] ) && $_REQUEST['save-settings'] == 'success' ) : ?>
24
+ <div id="message-save-settings" class="notice notice-success is-dismissible" style="margin: 10px 0px 10px 0;padding: 10px;"><strong><?php _e( 'Configuration settings saved', 'breeze' ); ?></strong></div>
25
+ <?php endif; ?>
26
+ <div class="wrap breeze-main">
27
+ <div class="breeze-header">
28
+ <a href="https://www.cloudways.com" target="_blank">
29
+ <div class="breeze-logo"></div>
30
+ </a>
31
+ </div>
32
+
33
+ <h1 style="clear: both"></h1>
34
+
35
+ <?php
36
+
37
+ $show_tabs = true;
38
+ $is_subsite = is_multisite() && get_current_screen()->base !== 'settings_page_breeze-network';
39
+
40
+ if ( $is_subsite ) {
41
+ // Show settings inherit option.
42
+ $inherit_settings = get_option( 'breeze_inherit_settings', 1 );
43
+ if ( 0 != $inherit_settings ) {
44
+ $inherit_settings = 1;
45
+ $show_tabs = false;
46
+ }
47
+ ?>
48
+ <form id="breeze-inherit-settings-toggle" class="breeze-form" method="post" action="">
49
+ <div class="radio-field<?php echo $inherit_settings == 1 ? ' active' : ''; ?>">
50
+ <label>
51
+ <input type="radio" id="inherit-settings" name="inherit-settings" value="1" <?php checked( $inherit_settings, 1 ); ?>>
52
+ <strong><?php esc_html_e( 'Use Network Level Settings for this site', 'breeze' ); ?>:</strong>
53
+ </label>
54
+ <small><?php esc_html_e( 'This option allows the subsite to inherit all the cache settings from network. To modify/update the settings please go to network site.', 'breeze' ); ?></small>
55
+ </div>
56
+ <div class="radio-field<?php echo $inherit_settings == 0 ? ' active' : ''; ?>">
57
+ <label>
58
+ <input type="radio" id="inherit-settings" name="inherit-settings" value="0" <?php checked( $inherit_settings, 0 ); ?>>
59
+ <strong><?php esc_html_e( 'Use Custom Settings for this site', 'breeze' ); ?>:</strong>
60
+ </label>
61
+ <small><?php esc_html_e( 'This option allows subsite to have different settings/configuration from the network level. Use this option only if you wish to have separate settings for this subsite.', 'breeze' ); ?></small>
62
+ </div>
63
+
64
+ <p class="disclaimer"><?php esc_html_e( 'To apply your changes, please click on the Save Changes button.', 'breeze' ); ?></p>
65
+
66
+ <?php wp_nonce_field( 'breeze_inherit_settings', 'breeze_inherit_settings_nonce' ); ?>
67
+ </form>
68
+
69
+ <h1 style="clear: both"></h1>
70
+ <?php
71
+ }
72
+ ?>
73
+
74
+ <ul id="breeze-tabs" class="nav-tab-wrapper <?php echo ! $show_tabs ? 'tabs-hidden' : ''; ?>">
75
+ <?php
76
+ foreach ( $tabs as $key => $name ) {
77
+ $is_inactive = ! $show_tabs && ! in_array( $key, $global_tabs );
78
+ echo '<a id="tab-' . $key . '" class="nav-tab' . ( $is_inactive ? ' inactive' : '' ) . '" href="#tab-' . $key . '" data-tab-id="' . $key . '"> ' . $name . ' </a> ';
79
+ }
80
+ ?>
81
+ </ul>
82
+
83
+ <div id="breeze-tabs-content" class="tab-content <?php echo ! $show_tabs ? 'tabs-hidden' : ''; ?>">
84
+ <?php
85
+ foreach ( $tabs as $key => $name ) {
86
+ $is_inactive = ! $show_tabs && ! in_array( $key, $global_tabs );
87
+ echo '<div id="tab-content-' . $key . '" class="tab-pane' . ( $is_inactive ? ' inactive' : '' ) . '">';
88
+ echo '<form class="breeze-form" method="post" action="">';
89
+ echo '<div class="tab-child">';
90
+ echo '<input type="hidden" name="breeze_' . $key . '_action" value="breeze_' . $key . '_settings">';
91
+ wp_nonce_field( 'breeze_settings_' . $key, 'breeze_settings_' . $key . '_nonce' );
92
+ Breeze_Admin::render( $key );
93
+ echo '</div>';
94
+
95
+ if (
96
+ $key != 'faq' &&
97
+ ( $key != 'database' || ( is_multisite() && ! is_network_admin() ) )
98
+ ) {
99
+ if ( is_multisite() && is_network_admin() ) {
100
+ echo '<p class="multisite-inherit-disclaimer">' . __( '* Any change here will also be applied to all the sub-sites that are using Network level settings.', 'wpr' ) . '</p>';
101
+ }
102
+ echo '<p class="submit">' . PHP_EOL .
103
+ '<input type="submit" class="button button-primary breeze-submit-btn" value="' . __( 'Save Changes', 'breeze' ) . '"/>' . PHP_EOL .
104
+ '</p>';
105
+ }
106
+ if ( ! in_array( $key, $global_tabs ) ) {
107
+ echo '<span class="hidden-text">' . esc_attr__( 'When Network Level Settings is selected, modifications/updates can only be done from the main Network site.', 'breeze' ) . '</span>';
108
+ }
109
+ echo '</form>';
110
+ echo '</div>';
111
+ }
112
+ ?>
113
+
114
+ <!--Right-side content-->
115
+ <div id="breeze-and-cloudways" class="rs-block">
116
+ <h3 class="rs-title"><?php _e( 'Want to Experience Better Performance?', 'breeze' ); ?></h3>
117
+ <div class="rs-content">
118
+ <p><?php _e( 'Take advantage of powerful features by deploying WordPress and Breeze on Cloudways.', 'breeze' ); ?></p>
119
+ <ul>
120
+ <li><?php _e( 'Fully Compatible with Varnish', 'breeze' ); ?></li>
121
+ <li><?php _e( 'One-Click setup of CloudwaysCDN', 'breeze' ); ?></li>
122
+ <li><?php _e( '24/7 Expert Human Support', 'breeze' ); ?></li>
123
+ <li><?php _e( 'WooCommerce Compatible', 'breeze' ); ?></li>
124
+ </ul>
125
+ <button class="button button-primary">
126
+ <a href="https://www.cloudways.com/en/wordpress-cloud-hosting.php?utm_source=breeze-plugin&utm_medium=breeze&utm_campaign=breeze" target="_blank"><?php _e( 'Find Out More', 'breeze' ); ?></a>
127
+ </button>
128
  </div>
129
+ <div class="rs-content">
130
+ <h4><?php _e( 'Rate Breeze', 'breeze' ); ?></h4>
131
+ <p><?php _e( 'If you are satisfied with Breeze\'s performance, <a href="https://wordpress.org/plugins/breeze#reviews" target="_blank">drop us a rating here.</a>', 'breeze' ); ?></p>
 
 
 
132
  </div>
133
+ </div>
134
+ </div>
135
+ </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
views/tabs/advanced.php CHANGED
@@ -45,8 +45,8 @@ if ( isset( $advanced['breeze-exclude-urls'] ) && ! empty( $advanced['breeze-exc
45
  href="https://support.cloudways.com/how-to-exclude-url-from-varnish/"
46
  target="_blank"><?php _e( 'Knowledge Base', 'breeze' ); ?></a><?php _e( ' article.', 'breeze' ); ?> </span>
47
  <?php if ( false === $excluded_url_list ) { ?>
48
- <br/>
49
- <span class="breeze_tool_tip" style="color: #ff0000">
50
  <?php _e( 'One (or more) URL is invalid. Please check and correct the entry.', 'breeze' ); ?>
51
  </span>
52
  <?php } ?>
45
  href="https://support.cloudways.com/how-to-exclude-url-from-varnish/"
46
  target="_blank"><?php _e( 'Knowledge Base', 'breeze' ); ?></a><?php _e( ' article.', 'breeze' ); ?> </span>
47
  <?php if ( false === $excluded_url_list ) { ?>
48
+ <br/>
49
+ <span class="breeze_tool_tip" style="color: #ff0000">
50
  <?php _e( 'One (or more) URL is invalid. Please check and correct the entry.', 'breeze' ); ?>
51
  </span>
52
  <?php } ?>
views/tabs/basic.php CHANGED
@@ -1,173 +1,173 @@
1
- <?php
2
- defined('ABSPATH') or die;
3
-
4
- $basic = breeze_get_option( 'basic_settings', true );
5
- ?>
6
- <table cellspacing="15">
7
- <tr>
8
- <td>
9
- <label for="cache-system"><?php _e('Cache System', 'breeze'); ?></label>
10
- </td>
11
- <td>
12
- <input type="checkbox" id="cache-system" name="cache-system"
13
- value='1' <?php checked($basic['breeze-active'], '1') ?>/>
14
- <span class="breeze_tool_tip">
15
- <?php _e('This is the basic cache that we recommend should be kept enabled in all cases. Basic cache will build the internal and static caches for the WordPress websites.', 'breeze') ?>
16
- </span>
17
- </td>
18
- </tr>
19
- <tr>
20
- <td>
21
- <label for="cache-ttl"><?php _e('Purge cache after', 'breeze'); ?></label>
22
- </td>
23
- <td>
24
- <input type="text" id="cache-ttl" size="5" name="cache-ttl"
25
- value='<?php echo(!empty($basic['breeze-ttl']) ? (int)$basic['breeze-ttl'] : '1440'); ?>'/>
26
- <span class="breeze_tool_tip" style="vertical-align: baseline">
27
- <?php _e('Automatically purge internal cache after X minutes. By default this is set to 1440 minutes (1 day)', 'breeze') ?>
28
- </span>
29
- </td>
30
- </tr>
31
- <tr>
32
- <td>
33
- <label class="breeze_tool_tip"><?php _e('Minification', 'breeze'); ?></label>
34
- </td>
35
- <td>
36
- <ul>
37
- <li>
38
- <input type="checkbox" name="minification-html" id="minification-html"
39
- value="1" <?php checked($basic['breeze-minify-html'], '1') ?>/>
40
- <label class="breeze_tool_tip" for="minification-html">
41
- <?php _e('HTML', 'breeze') ?>
42
- </label>
43
- </li>
44
- <li>
45
- <input type="checkbox" name="minification-css" id="minification-css"
46
- value="1" <?php checked($basic['breeze-minify-css'], '1') ?>/>
47
- <label class="breeze_tool_tip" for="minification-css">
48
- <?php _e('CSS', 'breeze') ?>
49
- </label>
50
- </li>
51
- <li>
52
- <input type="checkbox" name="minification-js" id="minification-js"
53
- value="1" <?php checked($basic['breeze-minify-js'], '1') ?>/>
54
- <label class="breeze_tool_tip" for="minification-js">
55
- <?php _e('JS', 'breeze') ?>
56
- </label>
57
- </li>
58
- <li>
59
- <input type="checkbox" name="include-inline-js" id="include-inline-js"
60
- value="1" <?php checked($basic['breeze-include-inline-js'], '1') ?>/>
61
- <label class="breeze_tool_tip" for="include-inline-js">
62
- <?php _e('Include inline JS', 'breeze') ?>
63
- </label>
64
- </li>
65
- <li>
66
- <input type="checkbox" name="include-inline-css" id="include-inline-css"
67
- value="1" <?php checked($basic['breeze-include-inline-css'], '1') ?>/>
68
- <label class="breeze_tool_tip" for="include-inline-css">
69
- <?php _e('Include inline CSS', 'breeze') ?>
70
- </label>
71
- </li>
72
- <li>
73
- <span><?php _e('Check the above boxes to minify HTML, CSS, or JS files.', 'breeze') ?></span>
74
- <br>
75
- <span>
76
- <b><?php esc_html_e( 'Note', 'breeze' ); ?>:&nbsp;</b>
77
- <span style="color: #ff0000"><?php _e('We recommend testing minification on a staging website before deploying it on a live website. Minification is known to cause issues on the frontend.', 'breeze') ?></span>
78
- </span>
79
- </li>
80
- </ul>
81
-
82
- </td>
83
- </tr>
84
-
85
- <?php
86
-
87
- $htaccess_options = array(
88
- 'gzip-compression' => array(
89
- 'label' => __( 'Gzip Compression', 'breeze' ),
90
- 'desc' => __( 'Enable this to compress your files making HTTP requests fewer and faster.', 'breeze' ),
91
- ),
92
- 'browser-cache' => array(
93
- 'label' => __( 'Browser Cache', 'breeze' ),
94
- 'desc' => __( 'Enable this to add expires headers to static files. This will ask browsers to either request a file from server or fetch from the browser’s cache.', 'breeze' ),
95
- ),
96
- );
97
-
98
- $supports_conditionals = breeze_is_supported( 'conditional_htaccess' );
99
-
100
- foreach ( $htaccess_options as $fid => $field ) {
101
- $is_disabled = is_multisite() && ! is_network_admin() && ! $supports_conditionals;
102
- $is_checked = isset( $basic[ 'breeze-' . $fid ] ) && '1' === $basic[ 'breeze-' . $fid ] && ! $is_disabled;
103
-
104
- ?>
105
- <tr>
106
- <td>
107
- <label for="<?php echo esc_attr( $fid ); ?>"><?php echo esc_html( $field['label'] ); ?></label>
108
- </td>
109
- <td>
110
- <input type="checkbox" id="<?php echo esc_attr( $fid ); ?>" name="<?php echo esc_attr( $fid ); ?>"
111
- value='1' <?php checked( $is_checked, true ); ?> <?php echo $is_disabled ? 'disabled="disabled"' : ''; ?>/>
112
- <span class="breeze_tool_tip"><?php echo esc_html( $field['desc'] ); ?></span>
113
- <?php if ( $is_disabled ) { ?>
114
  <br>
115
  <span>
116
- <b><?php esc_html_e( 'Note', 'breeze' ); ?>:&nbsp;</b>
117
- <span style="color: #ff0000"><?php printf( esc_html__( 'Enabling/disabling %s for subsites is only available for Apache 2.4 and above. For lower versions, the Network-level settings will apply.', 'breeze' ), $field['label'] ); ?></span>
118
  </span>
119
- <?php } ?>
120
- </td>
121
- </tr>
122
- <?php
123
- }
124
-
125
- ?>
126
-
127
- <tr style="display: none;">
128
- <td style="vertical-align: middle">
129
- <label for="desktop-cache" class="breeze_tool_tip"> <?php _e('Desktop Cache', 'breeze') ?></label>
130
- </td>
131
- <td>
132
- <select id="desktop-cache" name="desktop-cache">
133
- <option value="1" <?php echo ($basic['breeze-desktop-cache'] == '1') ? 'selected="selected"' : '' ?>><?php _e('Activated', 'breeze') ?></option>
134
- <option value="2" <?php echo ($basic['breeze-desktop-cache'] == '2') ? 'selected="selected"' : '' ?>><?php _e('No cache for desktop', 'breeze') ?></option>
135
- </select>
136
- </td>
137
- </tr>
138
-
139
- <tr style="display: none;">
140
- <td style="vertical-align: middle">
141
- <label for="mobile-cache" class="breeze_tool_tip"> <?php _e('Mobile Cache', 'breeze') ?></label>
142
- </td>
143
- <td>
144
- <select id="mobile-cache" name="mobile-cache">
145
- <option value="1" <?php echo ($basic['breeze-mobile-cache'] == '1') ? 'selected="selected"' : '' ?>><?php _e('Automatic (same as desktop)', 'breeze') ?></option>
146
- <option value="2" <?php echo ($basic['breeze-mobile-cache'] == '2') ? 'selected="selected"' : '' ?>><?php _e('Specific mobile cache', 'breeze') ?></option>
147
- <option value="3" <?php echo ($basic['breeze-mobile-cache'] == '3') ? 'selected="selected"' : '' ?>><?php _e('No cache for mobile', 'breeze') ?></option>
148
- </select>
149
- </td>
150
- </tr>
151
- <tr>
152
- <td>
153
- <label class="breeze_tool_tip"><?php _e('Enable cache for loggedin users', 'breeze'); ?></label>
154
- </td>
155
- <td>
156
- <ul>
157
- <li>
158
- <input type="checkbox" name="breeze-admin-cache" id="breeze-admin-cache"
159
- value="0" <?php checked($basic['breeze-disable-admin'], '0') ?>/>
160
- <label class="breeze_tool_tip" for="breeze-admin-cache">
161
- <?php _e('Enable cache for WP standard user roles: Administrator, Editor, Author, Contributor.', 'breeze') ?>
162
-
163
- </label>
164
- <br/>
165
- <span>
166
- <b><?php esc_html_e( 'Note', 'breeze' ); ?>:&nbsp;</b>
167
- <span style="color: #ff0000"><?php echo esc_html__( 'This option might not work properly with some page builders.', 'breeze' ) ?></span>
168
- </span>
169
- </li>
170
- </ul>
171
- </td>
172
- </tr>
173
- </table>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ defined( 'ABSPATH' ) or die;
3
+
4
+ $basic = breeze_get_option( 'basic_settings', true );
5
+ ?>
6
+ <table cellspacing="15">
7
+ <tr>
8
+ <td>
9
+ <label for="cache-system"><?php _e( 'Cache System', 'breeze' ); ?></label>
10
+ </td>
11
+ <td>
12
+ <input type="checkbox" id="cache-system" name="cache-system"
13
+ value='1' <?php checked( $basic['breeze-active'], '1' ); ?>/>
14
+ <span class="breeze_tool_tip">
15
+ <?php _e( 'This is the basic cache that we recommend should be kept enabled in all cases. Basic cache will build the internal and static caches for the WordPress websites.', 'breeze' ); ?>
16
+ </span>
17
+ </td>
18
+ </tr>
19
+ <tr>
20
+ <td>
21
+ <label for="cache-ttl"><?php _e( 'Purge cache after', 'breeze' ); ?></label>
22
+ </td>
23
+ <td>
24
+ <input type="text" id="cache-ttl" size="5" name="cache-ttl"
25
+ value='<?php echo( ! empty( $basic['breeze-ttl'] ) ? (int) $basic['breeze-ttl'] : '1440' ); ?>'/>
26
+ <span class="breeze_tool_tip" style="vertical-align: baseline">
27
+ <?php _e( 'Automatically purge internal cache after X minutes. By default this is set to 1440 minutes (1 day)', 'breeze' ); ?>
28
+ </span>
29
+ </td>
30
+ </tr>
31
+ <tr>
32
+ <td>
33
+ <label class="breeze_tool_tip"><?php _e( 'Minification', 'breeze' ); ?></label>
34
+ </td>
35
+ <td>
36
+ <ul>
37
+ <li>
38
+ <input type="checkbox" name="minification-html" id="minification-html"
39
+ value="1" <?php checked( $basic['breeze-minify-html'], '1' ); ?>/>
40
+ <label class="breeze_tool_tip" for="minification-html">
41
+ <?php _e( 'HTML', 'breeze' ); ?>
42
+ </label>
43
+ </li>
44
+ <li>
45
+ <input type="checkbox" name="minification-css" id="minification-css"
46
+ value="1" <?php checked( $basic['breeze-minify-css'], '1' ); ?>/>
47
+ <label class="breeze_tool_tip" for="minification-css">
48
+ <?php _e( 'CSS', 'breeze' ); ?>
49
+ </label>
50
+ </li>
51
+ <li>
52
+ <input type="checkbox" name="minification-js" id="minification-js"
53
+ value="1" <?php checked( $basic['breeze-minify-js'], '1' ); ?>/>
54
+ <label class="breeze_tool_tip" for="minification-js">
55
+ <?php _e( 'JS', 'breeze' ); ?>
56
+ </label>
57
+ </li>
58
+ <li>
59
+ <input type="checkbox" name="include-inline-js" id="include-inline-js"
60
+ value="1" <?php checked( $basic['breeze-include-inline-js'], '1' ); ?>/>
61
+ <label class="breeze_tool_tip" for="include-inline-js">
62
+ <?php _e( 'Include inline JS', 'breeze' ); ?>
63
+ </label>
64
+ </li>
65
+ <li>
66
+ <input type="checkbox" name="include-inline-css" id="include-inline-css"
67
+ value="1" <?php checked( $basic['breeze-include-inline-css'], '1' ); ?>/>
68
+ <label class="breeze_tool_tip" for="include-inline-css">
69
+ <?php _e( 'Include inline CSS', 'breeze' ); ?>
70
+ </label>
71
+ </li>
72
+ <li>
73
+ <span><?php _e( 'Check the above boxes to minify HTML, CSS, or JS files.', 'breeze' ); ?></span>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
  <br>
75
  <span>
76
+ <b><?php esc_html_e( 'Note', 'breeze' ); ?>:&nbsp;</b>
77
+ <span style="color: #ff0000"><?php _e( 'We recommend testing minification on a staging website before deploying it on a live website. Minification is known to cause issues on the frontend.', 'breeze' ); ?></span>
78
  </span>
79
+ </li>
80
+ </ul>
81
+
82
+ </td>
83
+ </tr>
84
+
85
+ <?php
86
+
87
+ $htaccess_options = array(
88
+ 'gzip-compression' => array(
89
+ 'label' => __( 'Gzip Compression', 'breeze' ),
90
+ 'desc' => __( 'Enable this to compress your files making HTTP requests fewer and faster.', 'breeze' ),
91
+ ),
92
+ 'browser-cache' => array(
93
+ 'label' => __( 'Browser Cache', 'breeze' ),
94
+ 'desc' => __( 'Enable this to add expires headers to static files. This will ask browsers to either request a file from server or fetch from the browser’s cache.', 'breeze' ),
95
+ ),
96
+ );
97
+
98
+ $supports_conditionals = breeze_is_supported( 'conditional_htaccess' );
99
+
100
+ foreach ( $htaccess_options as $fid => $field ) {
101
+ $is_disabled = is_multisite() && ! is_network_admin() && ! $supports_conditionals;
102
+ $is_checked = isset( $basic[ 'breeze-' . $fid ] ) && '1' === $basic[ 'breeze-' . $fid ] && ! $is_disabled;
103
+
104
+ ?>
105
+ <tr>
106
+ <td>
107
+ <label for="<?php echo esc_attr( $fid ); ?>"><?php echo esc_html( $field['label'] ); ?></label>
108
+ </td>
109
+ <td>
110
+ <input type="checkbox" id="<?php echo esc_attr( $fid ); ?>" name="<?php echo esc_attr( $fid ); ?>"
111
+ value='1' <?php checked( $is_checked, true ); ?> <?php echo $is_disabled ? 'disabled="disabled"' : ''; ?>/>
112
+ <span class="breeze_tool_tip"><?php echo esc_html( $field['desc'] ); ?></span>
113
+ <?php if ( $is_disabled ) { ?>
114
+ <br>
115
+ <span>
116
+ <b><?php esc_html_e( 'Note', 'breeze' ); ?>:&nbsp;</b>
117
+ <span style="color: #ff0000"><?php printf( esc_html__( 'Enabling/disabling %s for subsites is only available for Apache 2.4 and above. For lower versions, the Network-level settings will apply.', 'breeze' ), $field['label'] ); ?></span>
118
+ </span>
119
+ <?php } ?>
120
+ </td>
121
+ </tr>
122
+ <?php
123
+ }
124
+
125
+ ?>
126
+
127
+ <tr style="display: none;">
128
+ <td style="vertical-align: middle">
129
+ <label for="desktop-cache" class="breeze_tool_tip"> <?php _e( 'Desktop Cache', 'breeze' ); ?></label>
130
+ </td>
131
+ <td>
132
+ <select id="desktop-cache" name="desktop-cache">
133
+ <option value="1" <?php echo ( $basic['breeze-desktop-cache'] == '1' ) ? 'selected="selected"' : ''; ?>><?php _e( 'Activated', 'breeze' ); ?></option>
134
+ <option value="2" <?php echo ( $basic['breeze-desktop-cache'] == '2' ) ? 'selected="selected"' : ''; ?>><?php _e( 'No cache for desktop', 'breeze' ); ?></option>
135
+ </select>
136
+ </td>
137
+ </tr>
138
+
139
+ <tr style="display: none;">
140
+ <td style="vertical-align: middle">
141
+ <label for="mobile-cache" class="breeze_tool_tip"> <?php _e( 'Mobile Cache', 'breeze' ); ?></label>
142
+ </td>
143
+ <td>
144
+ <select id="mobile-cache" name="mobile-cache">
145
+ <option value="1" <?php echo ( $basic['breeze-mobile-cache'] == '1' ) ? 'selected="selected"' : ''; ?>><?php _e( 'Automatic (same as desktop)', 'breeze' ); ?></option>
146
+ <option value="2" <?php echo ( $basic['breeze-mobile-cache'] == '2' ) ? 'selected="selected"' : ''; ?>><?php _e( 'Specific mobile cache', 'breeze' ); ?></option>
147
+ <option value="3" <?php echo ( $basic['breeze-mobile-cache'] == '3' ) ? 'selected="selected"' : ''; ?>><?php _e( 'No cache for mobile', 'breeze' ); ?></option>
148
+ </select>
149
+ </td>
150
+ </tr>
151
+ <tr>
152
+ <td>
153
+ <label class="breeze_tool_tip"><?php _e( 'Enable cache for loggedin users', 'breeze' ); ?></label>
154
+ </td>
155
+ <td>
156
+ <ul>
157
+ <li>
158
+ <input type="checkbox" name="breeze-admin-cache" id="breeze-admin-cache"
159
+ value="0" <?php checked( $basic['breeze-disable-admin'], '0' ); ?>/>
160
+ <label class="breeze_tool_tip" for="breeze-admin-cache">
161
+ <?php _e( 'Enable cache for WP standard user roles: Administrator, Editor, Author, Contributor.', 'breeze' ); ?>
162
+
163
+ </label>
164
+ <br/>
165
+ <span>
166
+ <b><?php esc_html_e( 'Note', 'breeze' ); ?>:&nbsp;</b>
167
+ <span style="color: #ff0000"><?php echo esc_html__( 'This option might not work properly with some page builders.', 'breeze' ); ?></span>
168
+ </span>
169
+ </li>
170
+ </ul>
171
+ </td>
172
+ </tr>
173
+ </table>
views/tabs/cdn.php CHANGED
@@ -1,85 +1,85 @@
1
- <?php
2
- defined('ABSPATH') or die;
3
-
4
- $cdn_integration = breeze_get_option( 'cdn_integration', true );
5
-
6
- $cdn_content_value = '';
7
- $cdn_exclude_content_value = '';
8
- if(!empty($cdn_integration['cdn-content'])){
9
- $cdn_content_value = implode(',',$cdn_integration['cdn-content']);
10
- }
11
- if(!empty($cdn_integration['cdn-exclude-content'])){
12
- $cdn_exclude_content_value = implode(',',$cdn_integration['cdn-exclude-content']);
13
- }
14
- ?>
15
- <table cellspacing="15">
16
- <tr>
17
- <td>
18
- <label for="activate-cdn" class="breeze_tool_tip"><?php _e('Activate CDN', 'breeze')?></label>
19
- </td>
20
- <td>
21
- <input type="checkbox" id="activate-cdn" name="activate-cdn" value="1" <?php checked($cdn_integration['cdn-active'],'1')?>/>
22
- <span class="breeze_tool_tip"><?php _e('Enable to make CDN effective on your website.', 'breeze')?></span>
23
- </td>
24
- </tr>
25
- <tr>
26
- <td>
27
- <label for="cdn-url" class="breeze_tool_tip"><?php _e('CDN CNAME', 'breeze')?></label>
28
- </td>
29
- <td>
30
- <?php
31
- $cdn_url = ( ( $cdn_integration['cdn-url'] ) ? esc_html( $cdn_integration['cdn-url'] ) : '' );
32
- $cdn_url_validation = breeze_validate_url_via_regexp( $cdn_url );
33
- ?>
34
- <input type="text" id="cdn-url" name="cdn-url" size="50" placeholder="<?php _e('https://www.domain.com','breeze')?>" value="<?php echo $cdn_url; ?>"/>
35
- <span style="vertical-align: baseline" class="breeze_tool_tip"><?php _e('Enter CDN CNAME.', 'breeze')?></span>
36
- <br>
37
- <span class="breeze_tool_tip"><b>Note:&nbsp;</b><?php _e('Use double slash ‘//’ at the start of CDN CNAME, if you have some pages on HTTP and some are on HTTPS.', 'breeze') ?></span>
38
- <?php
39
- if ( false === $cdn_url_validation && ! empty( $cdn_url ) ) {
40
- ?>
41
- <br/>
42
- <span>
43
- <b><?php esc_html_e( 'Note', 'breeze' ); ?>:&nbsp;</b>
44
- <span style="color: #ff0000">
45
- <?php
46
- echo $cdn_url . ' ';
47
- echo esc_html__( 'is not a valid CDN url.', 'breeze' );
48
- ?>
49
- </span>
50
- </span>
51
- <?php
52
- }
53
- ?>
54
- </td>
55
- </tr>
56
- <tr>
57
- <td>
58
- <label for="cdn-content" class="breeze_tool_tip" ><?php _e('CDN Content', 'breeze')?></label>
59
- </td>
60
- <td>
61
- <input type="text" id="cdn-content" name="cdn-content" size="50" value="<?php echo (($cdn_content_value)?esc_html($cdn_content_value):''); ?>"/>
62
- <br>
63
- <span class="breeze_tool_tip"><b>Note:&nbsp;</b><?php _e('Enter the directories (comma separated) of which you want the CDN to serve the content.', 'breeze') ?></span>
64
- </td>
65
- </tr>
66
- <tr>
67
- <td>
68
- <label for="cdn-exclude-content" class="breeze_tool_tip" ><?php _e('Exclude Content', 'breeze')?></label>
69
- </td>
70
- <td>
71
- <input type="text" id="cdn-exclude-content" name="cdn-exclude-content" size="50" value="<?php echo (($cdn_exclude_content_value)?esc_html($cdn_exclude_content_value):''); ?>" />
72
- <br>
73
- <span class="breeze_tool_tip"><b>Note:&nbsp;</b><?php _e('Exclude file types or directories from CDN. Example, enter .css to exclude the CSS files.', 'breeze') ?></span>
74
- </td>
75
- </tr>
76
- <tr>
77
- <td>
78
- <label for="cdn-relative-path" class="breeze_tool_tip" ><?php _e('Relative path', 'breeze')?></label>
79
- </td>
80
- <td>
81
- <input type="checkbox" id="cdn-relative-path" name="cdn-relative-path" value="1" <?php checked($cdn_integration['cdn-relative-path'], '1')?>/>
82
- <span class="breeze_tool_tip"><?php _e('Keep this option enabled. Use this option to enable relative path for your CDN on your WordPress site.', 'breeze')?></span>
83
- </td>
84
- </tr>
85
- </table>
1
+ <?php
2
+ defined( 'ABSPATH' ) or die;
3
+
4
+ $cdn_integration = breeze_get_option( 'cdn_integration', true );
5
+
6
+ $cdn_content_value = '';
7
+ $cdn_exclude_content_value = '';
8
+ if ( ! empty( $cdn_integration['cdn-content'] ) ) {
9
+ $cdn_content_value = implode( ',', $cdn_integration['cdn-content'] );
10
+ }
11
+ if ( ! empty( $cdn_integration['cdn-exclude-content'] ) ) {
12
+ $cdn_exclude_content_value = implode( ',', $cdn_integration['cdn-exclude-content'] );
13
+ }
14
+ ?>
15
+ <table cellspacing="15">
16
+ <tr>
17
+ <td>
18
+ <label for="activate-cdn" class="breeze_tool_tip"><?php _e( 'Activate CDN', 'breeze' ); ?></label>
19
+ </td>
20
+ <td>
21
+ <input type="checkbox" id="activate-cdn" name="activate-cdn" value="1" <?php checked( $cdn_integration['cdn-active'], '1' ); ?>/>
22
+ <span class="breeze_tool_tip"><?php _e( 'Enable to make CDN effective on your website.', 'breeze' ); ?></span>
23
+ </td>
24
+ </tr>
25
+ <tr>
26
+ <td>
27
+ <label for="cdn-url" class="breeze_tool_tip"><?php _e( 'CDN CNAME', 'breeze' ); ?></label>
28
+ </td>
29
+ <td>
30
+ <?php
31
+ $cdn_url = ( ( $cdn_integration['cdn-url'] ) ? esc_html( $cdn_integration['cdn-url'] ) : '' );
32
+ $cdn_url_validation = breeze_validate_url_via_regexp( $cdn_url );
33
+ ?>
34
+ <input type="text" id="cdn-url" name="cdn-url" size="50" placeholder="<?php _e( 'https://www.domain.com', 'breeze' ); ?>" value="<?php echo $cdn_url; ?>"/>
35
+ <span style="vertical-align: baseline" class="breeze_tool_tip"><?php _e( 'Enter CDN CNAME.', 'breeze' ); ?></span>
36
+ <br>
37
+ <span class="breeze_tool_tip"><b>Note:&nbsp;</b><?php _e( 'Use double slash ‘//’ at the start of CDN CNAME, if you have some pages on HTTP and some are on HTTPS.', 'breeze' ); ?></span>
38
+ <?php
39
+ if ( false === $cdn_url_validation && ! empty( $cdn_url ) ) {
40
+ ?>
41
+ <br/>
42
+ <span>
43
+ <b><?php esc_html_e( 'Note', 'breeze' ); ?>:&nbsp;</b>
44
+ <span style="color: #ff0000">
45
+ <?php
46
+ echo $cdn_url . ' ';
47
+ echo esc_html__( 'is not a valid CDN url.', 'breeze' );
48
+ ?>
49
+ </span>
50
+ </span>
51
+ <?php
52
+ }
53
+ ?>
54
+ </td>
55
+ </tr>
56
+ <tr>
57
+ <td>
58
+ <label for="cdn-content" class="breeze_tool_tip" ><?php _e( 'CDN Content', 'breeze' ); ?></label>
59
+ </td>
60
+ <td>
61
+ <input type="text" id="cdn-content" name="cdn-content" size="50" value="<?php echo ( ( $cdn_content_value ) ? esc_html( $cdn_content_value ) : '' ); ?>"/>
62
+ <br>
63
+ <span class="breeze_tool_tip"><b>Note:&nbsp;</b><?php _e( 'Enter the directories (comma separated) of which you want the CDN to serve the content.', 'breeze' ); ?></span>
64
+ </td>
65
+ </tr>
66
+ <tr>
67
+ <td>
68
+ <label for="cdn-exclude-content" class="breeze_tool_tip" ><?php _e( 'Exclude Content', 'breeze' ); ?></label>
69
+ </td>
70
+ <td>
71
+ <input type="text" id="cdn-exclude-content" name="cdn-exclude-content" size="50" value="<?php echo ( ( $cdn_exclude_content_value ) ? esc_html( $cdn_exclude_content_value ) : '' ); ?>" />
72
+ <br>
73
+ <span class="breeze_tool_tip"><b>Note:&nbsp;</b><?php _e( 'Exclude file types or directories from CDN. Example, enter .css to exclude the CSS files.', 'breeze' ); ?></span>
74
+ </td>
75
+ </tr>
76
+ <tr>
77
+ <td>
78
+ <label for="cdn-relative-path" class="breeze_tool_tip" ><?php _e( 'Relative path', 'breeze' ); ?></label>
79
+ </td>
80
+ <td>
81
+ <input type="checkbox" id="cdn-relative-path" name="cdn-relative-path" value="1" <?php checked( $cdn_integration['cdn-relative-path'], '1' ); ?>/>
82
+ <span class="breeze_tool_tip"><?php _e( 'Keep this option enabled. Use this option to enable relative path for your CDN on your WordPress site.', 'breeze' ); ?></span>
83
+ </td>
84
+ </tr>
85
+ </table>
views/tabs/database.php CHANGED
@@ -1,112 +1,117 @@
1
- <?php
2
-
3
- defined('ABSPATH') or die;
4
-
5
- $post_revisions = 0; $drafted = 0; $trashed = 0; $comments = 0; $trackbacks = 0; $transients = 0;
6
-
7
- if ( is_multisite() && is_network_admin() ) {
8
- // Count items from all network sites.
9
- $sites = get_sites(
10
- array(
11
- 'fields' => 'ids',
12
- )
13
- );
14
-
15
- foreach ( $sites as $blog_id ) {
16
- switch_to_blog( $blog_id );
17
- $post_revisions += (int) Breeze_Configuration::getElementToClean( 'revisions' );
18
- $drafted += (int) Breeze_Configuration::getElementToClean( 'drafted' );
19
- $trashed += (int) Breeze_Configuration::getElementToClean( 'trash' );
20
- $comments += (int) Breeze_Configuration::getElementToClean( 'comments' );
21
- $trackbacks += (int) Breeze_Configuration::getElementToClean( 'trackbacks' );
22
- $transients += (int) Breeze_Configuration::getElementToClean( 'transient' );
23
- restore_current_blog();
24
- }
25
- } else {
26
- // Count items from the current site.
27
- $post_revisions = (int) Breeze_Configuration::getElementToClean( 'revisions' );
28
- $drafted = (int) Breeze_Configuration::getElementToClean( 'drafted' );
29
- $trashed = (int) Breeze_Configuration::getElementToClean( 'trash' );
30
- $comments = (int) Breeze_Configuration::getElementToClean( 'comments' );
31
- $trackbacks = (int) Breeze_Configuration::getElementToClean( 'trackbacks' );
32
- $transients = (int) Breeze_Configuration::getElementToClean( 'transient' );
33
- }
34
-
35
- $is_optimize_disabled = is_multisite() && ! is_network_admin() && '0' !== get_option( 'breeze_inherit_settings' );
36
-
37
- ?>
38
- <div class="breeze-top-notice">
39
- <p class="breeze_tool_tip"><?php _e('Important: Backup your databases before using the following options!','breeze')?></p>
40
- </div>
41
- <table cellspacing="15">
42
- <tr>
43
- <td>
44
- <label for="data0" class="breeze_tool_tip"><?php _e('Select all','breeze')?></label>
45
- </td>
46
- <td>
47
- <input type="checkbox" id="data0" name="all_control" value="all_data"/>
48
- <span class="breeze_tool_tip"><?php _e('Select all following options. Click Optimize to perform actions.','breeze')?></span>
49
- </td>
50
- </tr>
51
- <tr>
52
- <td>
53
- <label for="data1" class="breeze_tool_tip"><?php _e('Post revisions','breeze')?><?php echo "&nbsp(".$post_revisions.")"; ?></label>
54
- </td>
55
- <td>
56
- <input type="checkbox" id="data1" name="clean[]" class="clean-data" value="revisions"/>
57
- <span class="breeze_tool_tip"><?php _e('Use this option to delete all post revisions from the WordPress database.','breeze')?></span>
58
- </td>
59
- </tr>
60
- <tr>
61
- <td>
62
- <label for="data2" class="breeze_tool_tip" ><?php _e('Auto drafted content','breeze')?><?php echo "&nbsp(".$drafted.")"; ?></label>
63
- </td>
64
- <td>
65
- <input type="checkbox" id="data2" name="clean[]" class="clean-data" value="drafted"/>
66
- <span class="breeze_tool_tip"><?php _e('Use this option to delete auto saved drafts from the WordPress database.','breeze')?></span>
67
- </td>
68
- </tr>
69
- <tr>
70
- <td>
71
- <label for="data3" class="breeze_tool_tip" ><?php _e('All trashed content','breeze')?><?php echo "&nbsp(".$trashed.")"; ?></label>
72
- </td>
73
- <td>
74
- <input type="checkbox" id="data3" name="clean[]" class="clean-data" value="trash"/>
75
- <span class="breeze_tool_tip"><?php _e('Use this option to delete all trashed content from the WordPress database.','breeze')?></span>
76
-
77
- </td>
78
- </tr>
79
- <tr>
80
- <td>
81
- <label for="data4" class="breeze_tool_tip" ><?php _e('Comments from trash & spam','breeze')?><?php echo "&nbsp(".$comments.")"; ?></label>
82
- </td>
83
- <td>
84
- <input type="checkbox" id="data4" name="clean[]" class="clean-data" value="comments"/>
85
- <span class="breeze_tool_tip"><?php _e('Use this option to delete trash and spam comments from the WordPress database.','breeze')?></span>
86
- </td>
87
- </tr>
88
- <tr>
89
- <td>
90
- <label for="data5" class="breeze_tool_tip" ><?php _e('Trackbacks and pingbacks','breeze')?><?php echo "&nbsp(".$trackbacks.")"; ?></label>
91
- </td>
92
- <td>
93
- <input type="checkbox" id="data5" name="clean[]" class="clean-data" value="trackbacks"/>
94
- <span class="breeze_tool_tip"><?php _e('Use this option to delete Trackbacks and Pingbacks from the WordPress database.','breeze')?></span>
95
- </td>
96
- </tr>
97
- <tr>
98
- <td>
99
- <label for="data6" class="breeze_tool_tip" ><?php _e('Transient options','breeze')?><?php echo "&nbsp(".$transients.")"; ?></label>
100
- </td>
101
- <td>
102
- <input type="checkbox" id="data6" name="clean[]" class="clean-data" value="transient"/>
103
- <span class="breeze_tool_tip"><?php _e('Delete expired and active transients from the WordPress database.','breeze')?></span>
104
- </td>
105
  </tr>
106
  <tr>
107
- <td></td>
108
  <td>
109
- <input type="submit" id="breeze-database-optimize" class="button button-primary" <?php echo $is_optimize_disabled ? ' disabled="disabled"' : ''; ?> value="<?php esc_attr_e( 'Optimize' ); ?>">
 
 
 
 
110
  </td>
111
  </tr>
112
- </table>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ defined( 'ABSPATH' ) or die;
4
+
5
+ $post_revisions = 0;
6
+ $drafted = 0;
7
+ $trashed = 0;
8
+ $comments = 0;
9
+ $trackbacks = 0;
10
+ $transients = 0;
11
+
12
+ if ( is_multisite() && is_network_admin() ) {
13
+ // Count items from all network sites.
14
+ $sites = get_sites(
15
+ array(
16
+ 'fields' => 'ids',
17
+ )
18
+ );
19
+
20
+ foreach ( $sites as $blog_id ) {
21
+ switch_to_blog( $blog_id );
22
+ $post_revisions += (int) Breeze_Configuration::getElementToClean( 'revisions' );
23
+ $drafted += (int) Breeze_Configuration::getElementToClean( 'drafted' );
24
+ $trashed += (int) Breeze_Configuration::getElementToClean( 'trash' );
25
+ $comments += (int) Breeze_Configuration::getElementToClean( 'comments' );
26
+ $trackbacks += (int) Breeze_Configuration::getElementToClean( 'trackbacks' );
27
+ $transients += (int) Breeze_Configuration::getElementToClean( 'transient' );
28
+ restore_current_blog();
29
+ }
30
+ } else {
31
+ // Count items from the current site.
32
+ $post_revisions = (int) Breeze_Configuration::getElementToClean( 'revisions' );
33
+ $drafted = (int) Breeze_Configuration::getElementToClean( 'drafted' );
34
+ $trashed = (int) Breeze_Configuration::getElementToClean( 'trash' );
35
+ $comments = (int) Breeze_Configuration::getElementToClean( 'comments' );
36
+ $trackbacks = (int) Breeze_Configuration::getElementToClean( 'trackbacks' );
37
+ $transients = (int) Breeze_Configuration::getElementToClean( 'transient' );
38
+ }
39
+
40
+ $is_optimize_disabled = is_multisite() && ! is_network_admin() && '0' !== get_option( 'breeze_inherit_settings' );
41
+
42
+ ?>
43
+ <div class="breeze-top-notice">
44
+ <p class="breeze_tool_tip"><?php _e( 'Important: Backup your databases before using the following options!', 'breeze' ); ?></p>
45
+ </div>
46
+ <table cellspacing="15">
47
+ <tr>
48
+ <td>
49
+ <label for="data0" class="breeze_tool_tip"><?php _e( 'Select all', 'breeze' ); ?></label>
50
+ </td>
51
+ <td>
52
+ <input type="checkbox" id="data0" name="all_control" value="all_data"/>
53
+ <span class="breeze_tool_tip"><?php _e( 'Select all following options. Click Optimize to perform actions.', 'breeze' ); ?></span>
54
+ </td>
55
+ </tr>
56
+ <tr>
57
+ <td>
58
+ <label for="data1" class="breeze_tool_tip"><?php _e( 'Post revisions', 'breeze' ); ?><?php echo '&nbsp(' . $post_revisions . ')'; ?></label>
59
+ </td>
60
+ <td>
61
+ <input type="checkbox" id="data1" name="clean[]" class="clean-data" value="revisions"/>
62
+ <span class="breeze_tool_tip"><?php _e( 'Use this option to delete all post revisions from the WordPress database.', 'breeze' ); ?></span>
63
+ </td>
64
+ </tr>
65
+ <tr>
66
+ <td>
67
+ <label for="data2" class="breeze_tool_tip" ><?php _e( 'Auto drafted content', 'breeze' ); ?><?php echo '&nbsp(' . $drafted . ')'; ?></label>
68
+ </td>
69
+ <td>
70
+ <input type="checkbox" id="data2" name="clean[]" class="clean-data" value="drafted"/>
71
+ <span class="breeze_tool_tip"><?php _e( 'Use this option to delete auto saved drafts from the WordPress database.', 'breeze' ); ?></span>
72
+ </td>
73
+ </tr>
74
+ <tr>
75
+ <td>
76
+ <label for="data3" class="breeze_tool_tip" ><?php _e( 'All trashed content', 'breeze' ); ?><?php echo '&nbsp(' . $trashed . ')'; ?></label>
77
+ </td>
78
+ <td>
79
+ <input type="checkbox" id="data3" name="clean[]" class="clean-data" value="trash"/>
80
+ <span class="breeze_tool_tip"><?php _e( 'Use this option to delete all trashed content from the WordPress database.', 'breeze' ); ?></span>
81
+
82
+ </td>
83
+ </tr>
84
+ <tr>
85
+ <td>
86
+ <label for="data4" class="breeze_tool_tip" ><?php _e( 'Comments from trash & spam', 'breeze' ); ?><?php echo '&nbsp(' . $comments . ')'; ?></label>
87
+ </td>
88
+ <td>
89
+ <input type="checkbox" id="data4" name="clean[]" class="clean-data" value="comments"/>
90
+ <span class="breeze_tool_tip"><?php _e( 'Use this option to delete trash and spam comments from the WordPress database.', 'breeze' ); ?></span>
91
+ </td>
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  </tr>
93
  <tr>
 
94
  <td>
95
+ <label for="data5" class="breeze_tool_tip" ><?php _e( 'Trackbacks and pingbacks', 'breeze' ); ?><?php echo '&nbsp(' . $trackbacks . ')'; ?></label>
96
+ </td>
97
+ <td>
98
+ <input type="checkbox" id="data5" name="clean[]" class="clean-data" value="trackbacks"/>
99
+ <span class="breeze_tool_tip"><?php _e( 'Use this option to delete Trackbacks and Pingbacks from the WordPress database.', 'breeze' ); ?></span>
100
  </td>
101
  </tr>
102
+ <tr>
103
+ <td>
104
+ <label for="data6" class="breeze_tool_tip" ><?php _e( 'Transient options', 'breeze' ); ?><?php echo '&nbsp(' . $transients . ')'; ?></label>
105
+ </td>
106
+ <td>
107
+ <input type="checkbox" id="data6" name="clean[]" class="clean-data" value="transient"/>
108
+ <span class="breeze_tool_tip"><?php _e( 'Delete expired and active transients from the WordPress database.', 'breeze' ); ?></span>
109
+ </td>
110
+ </tr>
111
+ <tr>
112
+ <td></td>
113
+ <td>
114
+ <input type="submit" id="breeze-database-optimize" class="button button-primary" <?php echo $is_optimize_disabled ? ' disabled="disabled"' : ''; ?> value="<?php esc_attr_e( 'Optimize' ); ?>">
115
+ </td>
116
+ </tr>
117
+ </table>
views/tabs/faq.php CHANGED
@@ -1,158 +1,158 @@
1
- <?php
2
- defined('ABSPATH') or die;
3
- ?>
4
- <div id="faq-content">
5
- <div class="faq-block">
6
- <h3 class="faq-question"><?php _e('Does Breeze support Varnish and to what extent?', 'breeze') ?></h3>
7
- <div class="faq-answer">
8
- <p><?php _e('Breeze, by default, supports Varnish. It has been tested to be fully compatible with Cloudways Servers that come with Varnish pre-installed. If you are using hosting providers other than Cloudways, we suggest you confirm Varnish support with your hosting provider.', 'breeze') ?></p>
9
- </div>
10
- </div>
11
-
12
- <div class="faq-block">
13
- <h3 class="faq-question"><?php _e('Does Breeze support WooCommerce?', 'breeze') ?></h3>
14
- <div class="faq-answer">
15
- <p><?php _e('Breeze is fully compatible with WooCommerce, out of the box. It does not require any special configurations.', 'breeze') ?></p>
16
- </div>
17
- </div>
18
-
19
- <div class="faq-block">
20
- <h3 class="faq-question"><?php _e('Does Breeze support WordPress Multisite?', 'breeze') ?></h3>
21
- <div class="faq-answer">
22
- <p><?php _e('Breeze is fully compatible with WordPress Multisite without the need for any extra configuration.', 'breeze') ?></p>
23
- </div>
24
- </div>
25
-
26
- <div class="faq-block">
27
- <h3 class="faq-question"><?php _e('How does Breeze handle WordPress multisite?', 'breeze') ?></h3>
28
- <div class="faq-answer">
29
- <p><?php _e('Breeze handles all WordPress multisite instances globally. All the settings for multisite are now handled on the network level.', 'breeze') ?></p>
30
- </div>
31
- </div>
32
-
33
- <div class="faq-block">
34
- <h3 class="faq-question"><?php _e('Is Breeze compatible with other WordPress Cache plugins?', 'breeze') ?></h3>
35
- <div class="faq-answer">
36
- <p><?php _e('We DO NOT recommend using two WordPress cache plugins at the same time on any WordPress website.', 'breeze') ?></p>
37
- <p><?php _e('We strongly recommend that you use Breeze as the only cache plugin for your website. If there are any other cache plugins installed, please ensure that you have disabled them prior to proceeding with the Breeze installation.', 'breeze') ?></p>
38
- </div>
39
- </div>
40
-
41
- <div class="faq-block">
42
- <h3 class="faq-question"><?php _e('Is Breeze compatible with HTTPS?', 'breeze') ?></h3>
43
- <div class="faq-answer">
44
- <p><?php _e('Breeze does not require any special configuration to work with HTTP or HTTPS pages.', 'breeze') ?></p>
45
- </div>
46
- </div>
47
-
48
- <div class="faq-block">
49
- <h3 class="faq-question"><?php _e('Does Breeze have compatibility issues with other known plugins?', 'breeze') ?></h3>
50
- <div class="faq-answer">
51
- <p><?php _e('Breeze has been tested with popular plugins available on WordPress.org. Please feel free to report any incompatibilities on the WordPress Support Forums or on ', 'breeze') ?>
52
- <a href="https://community.cloudways.com/" target="_blank"><?php _e('Cloudways Community Forum.', 'breeze') ?></a>
53
- </p>
54
- </div>
55
- </div>
56
-
57
- <div class="faq-block">
58
- <h3 class="faq-question"><?php _e('Does Breeze support CDN?', 'breeze') ?></h3>
59
- <div class="faq-answer">
60
- <p><?php _e('Breeze supports CDN integration. It allows all static assets (such as images, CSS and JS files) to be served via CDN.', 'breeze') ?></p>
61
- </div>
62
- </div>
63
-
64
- <div class="faq-block">
65
- <h3 class="faq-question"><?php _e('What does Breeze’s Database Optimization feature do?', 'breeze') ?></h3>
66
- <div class="faq-answer">
67
- <p><?php _e('WordPress databases are notorious for storing information like post revisions, spam comments and much more. Over time, databases l become bloated and it is a good practice to clear out unwanted information to reduce database size and improve optimization.', 'breeze') ?></p>
68
- <p><?php _e('Breeze’s database optimization cleans out unwanted information in a single click.', 'breeze') ?></p>
69
- </div>
70
- </div>
71
-
72
- <div class="faq-block">
73
- <h3 class="faq-question"><?php _e('Will comments and other dynamic parts of my blog appear immediately?', 'breeze') ?></h3>
74
- <div class="faq-answer">
75
- <p><?php _e('Comments will appear upon moderation as per the comment system (or policy) set in place by the blog owner. Other dynamic changes such as any modifications in files will require a full cache purge.', 'breeze') ?></p>
76
- </div>
77
- </div>
78
-
79
- <div class="faq-block">
80
- <h3 class="faq-question"><?php _e('Can I exclude URLs of individual files and pages from cache?', 'breeze') ?></h3>
81
- <div class="faq-answer">
82
- <p><?php _e('You can exclude a file by mentioning its URL or file type (by mentioning file extension) in the exclude fields (available in the Breeze settings). Exclude will not let the cache impact that URL or file type.', 'breeze') ?></p>
83
- <p><?php _e('If Varnish is active, you will need to exclude URLs and file type(s) in the Varnish configuration. If you are hosting WordPress websites on Cloudways servers, follow ', 'breeze') ?>
84
- <a href="https://support.cloudways.com/how-to-exclude-url-from-varnish/" target="_blank"><?php _e('this KB to exclude URLs from the Varnish cache.', 'breeze') ?></a>
85
- </p>
86
- </div>
87
- </div>
88
-
89
- <div class="faq-block">
90
- <h3 class="faq-question"><?php _e('Does it work with all hosting providers?', 'breeze') ?></h3>
91
- <div class="faq-answer">
92
- <p><?php _e('Breeze has been tested to work with all major hosting providers. In addition, major Breeze options such as Gzip, browser cache, minification, grouping, database optimization. CDN integration will work as expected on all hosting providers.', 'breeze') ?></p>
93
- </div>
94
- </div>
95
-
96
- <div class="faq-block">
97
- <h3 class="faq-question"><?php _e('Where can I get support for Breeze?', 'breeze') ?></h3>
98
- <div class="faq-answer">
99
- <p><?php _e('You can get your questions answered on the WordPress support forums. If you are a Cloudways customer, please feel free to start a discussion at', 'breeze') ?>
100
- <a href="https://community.cloudways.com/" target="_blank"><?php _e('Cloudways Community Forum.', 'breeze') ?></a>
101
- </p>
102
- </div>
103
- </div>
104
-
105
- <div class="faq-block">
106
- <h3 class="faq-question"><?php _e('How can I test and verify the results?', 'breeze') ?></h3>
107
- <div class="faq-answer">
108
- <p><?php _e('You will be able to see the impact of the Breeze Cache Plugin almost immediately. We also recommend using the following tools for generating metrics:', 'breeze') ?></p>
109
- <ul style="margin-top: 10px">
110
- <li><a href="https://developers.google.com/speed/pagespeed/" target="_blank"><?php _e('Google Page Speed', 'breeze') ?></a></li>
111
- <li><a href="https://www.webpagetest.org/test" target="_blank"><?php _e('WebPagetest', 'breeze') ?></a></li>
112
- <li><a href="https://tools.pingdom.com/" target="_blank"><?php _e('Pingdom', 'breeze') ?></a></li>
113
- </ul>
114
- </div>
115
- </div>
116
-
117
- <div class="faq-block">
118
- <h3 class="faq-question"><?php _e('Does Breeze plugin work with Visual Builder?', 'breeze') ?></h3>
119
- <div class="faq-answer">
120
- <p><?php _e('Yes, Breeze Plugin is compatible with Visual Builder.', 'breeze') ?></p>
121
- </div>
122
- </div>
123
-
124
- <div class="faq-block">
125
- <h3 class="faq-question"><?php _e('What popular CDN are supported by Breeze Plugin?', 'breeze') ?></h3>
126
- <div class="faq-answer">
127
- <p><?php _e('Breeze supports the following three popular CDNs:', 'breeze') ?></p>
128
- <ul style="margin-top: 10px">
129
- <li><a href="https://support.cloudways.com/how-to-use-breeze-with-maxcdn/" target="_blank"><?php _e('MaxCDN', 'breeze') ?></a></li>
130
- <li><a href="https://support.cloudways.com/how-to-use-breeze-with-keycdn/" target="_blank"><?php _e('KeyCDN', 'breeze') ?></a></li>
131
- <li><a href="https://support.cloudways.com/how-to-use-breeze-with-amazon-cloudfront/" target="_blank"><?php _e('Amazon Cloudfront', 'breeze') ?></a></li>
132
- </ul>
133
- </div>
134
- </div>
135
-
136
- <div class="faq-block">
137
- <h3 class="faq-question"><?php _e('Does Breeze support Push CDN?', 'breeze') ?></h3>
138
- <div class="faq-answer">
139
- <p><?php _e('No, Breeze does not support Push CDN. However, you could use Breeze with Push CDNs using third party plugins.', 'breeze') ?></p>
140
- </div>
141
- </div>
142
-
143
- <div class="faq-block">
144
- <h3 class="faq-question"><?php _e('Does Breeze Work With CloudFlare?', 'breeze') ?></h3>
145
- <div class="faq-answer">
146
- <p><?php _e('Yes. The process of setting up CloudFlare with Breeze is easy. Check out the following ', 'breeze') ?>
147
- <a href="https://support.cloudways.com/can-i-use-cloudflare-cdn/" target="_blank"><?php _e('KnowledgeBase article for details.', 'breeze') ?></a>
148
- </p>
149
- </div>
150
- </div>
151
-
152
- <div class="faq-block">
153
- <h3 class="faq-question"><?php _e('How Breeze cache uses Gzip?', 'breeze') ?></h3>
154
- <div class="faq-answer">
155
- <p><?php _e('Using Gzip, Breeze compresses the request files, further reducing the size of the download files and speeding up the user experience.', 'breeze') ?></p>
156
- </div>
157
- </div>
158
- </div>
1
+ <?php
2
+ defined( 'ABSPATH' ) or die;
3
+ ?>
4
+ <div id="faq-content">
5
+ <div class="faq-block">
6
+ <h3 class="faq-question"><?php _e( 'Does Breeze support Varnish and to what extent?', 'breeze' ); ?></h3>
7
+ <div class="faq-answer">
8
+ <p><?php _e( 'Breeze, by default, supports Varnish. It has been tested to be fully compatible with Cloudways Servers that come with Varnish pre-installed. If you are using hosting providers other than Cloudways, we suggest you confirm Varnish support with your hosting provider.', 'breeze' ); ?></p>
9
+ </div>
10
+ </div>
11
+
12
+ <div class="faq-block">
13
+ <h3 class="faq-question"><?php _e( 'Does Breeze support WooCommerce?', 'breeze' ); ?></h3>
14
+ <div class="faq-answer">
15
+ <p><?php _e( 'Breeze is fully compatible with WooCommerce, out of the box. It does not require any special configurations.', 'breeze' ); ?></p>
16
+ </div>
17
+ </div>
18
+
19
+ <div class="faq-block">
20
+ <h3 class="faq-question"><?php _e( 'Does Breeze support WordPress Multisite?', 'breeze' ); ?></h3>
21
+ <div class="faq-answer">
22
+ <p><?php _e( 'Breeze is fully compatible with WordPress Multisite without the need for any extra configuration.', 'breeze' ); ?></p>
23
+ </div>
24
+ </div>
25
+
26
+ <div class="faq-block">
27
+ <h3 class="faq-question"><?php _e( 'How does Breeze handle WordPress multisite?', 'breeze' ); ?></h3>
28
+ <div class="faq-answer">
29
+ <p><?php _e( 'Breeze handles all WordPress multisite instances globally. All the settings for multisite are now handled on the network level.', 'breeze' ); ?></p>
30
+ </div>
31
+ </div>
32
+
33
+ <div class="faq-block">
34
+ <h3 class="faq-question"><?php _e( 'Is Breeze compatible with other WordPress Cache plugins?', 'breeze' ); ?></h3>
35
+ <div class="faq-answer">
36
+ <p><?php _e( 'We DO NOT recommend using two WordPress cache plugins at the same time on any WordPress website.', 'breeze' ); ?></p>
37
+ <p><?php _e( 'We strongly recommend that you use Breeze as the only cache plugin for your website. If there are any other cache plugins installed, please ensure that you have disabled them prior to proceeding with the Breeze installation.', 'breeze' ); ?></p>
38
+ </div>
39
+ </div>
40
+
41
+ <div class="faq-block">
42
+ <h3 class="faq-question"><?php _e( 'Is Breeze compatible with HTTPS?', 'breeze' ); ?></h3>
43
+ <div class="faq-answer">
44
+ <p><?php _e( 'Breeze does not require any special configuration to work with HTTP or HTTPS pages.', 'breeze' ); ?></p>
45
+ </div>
46
+ </div>
47
+
48
+ <div class="faq-block">
49
+ <h3 class="faq-question"><?php _e( 'Does Breeze have compatibility issues with other known plugins?', 'breeze' ); ?></h3>
50
+ <div class="faq-answer">
51
+ <p><?php _e( 'Breeze has been tested with popular plugins available on WordPress.org. Please feel free to report any incompatibilities on the WordPress Support Forums or on ', 'breeze' ); ?>
52
+ <a href="https://community.cloudways.com/" target="_blank"><?php _e( 'Cloudways Community Forum.', 'breeze' ); ?></a>
53
+ </p>
54
+ </div>
55
+ </div>
56
+
57
+ <div class="faq-block">
58
+ <h3 class="faq-question"><?php _e( 'Does Breeze support CDN?', 'breeze' ); ?></h3>
59
+ <div class="faq-answer">
60
+ <p><?php _e( 'Breeze supports CDN integration. It allows all static assets (such as images, CSS and JS files) to be served via CDN.', 'breeze' ); ?></p>
61
+ </div>
62
+ </div>
63
+
64
+ <div class="faq-block">
65
+ <h3 class="faq-question"><?php _e( 'What does Breeze’s Database Optimization feature do?', 'breeze' ); ?></h3>
66
+ <div class="faq-answer">
67
+ <p><?php _e( 'WordPress databases are notorious for storing information like post revisions, spam comments and much more. Over time, databases l become bloated and it is a good practice to clear out unwanted information to reduce database size and improve optimization.', 'breeze' ); ?></p>
68
+ <p><?php _e( 'Breeze’s database optimization cleans out unwanted information in a single click.', 'breeze' ); ?></p>
69
+ </div>
70
+ </div>
71
+
72
+ <div class="faq-block">
73
+ <h3 class="faq-question"><?php _e( 'Will comments and other dynamic parts of my blog appear immediately?', 'breeze' ); ?></h3>
74
+ <div class="faq-answer">
75
+ <p><?php _e( 'Comments will appear upon moderation as per the comment system (or policy) set in place by the blog owner. Other dynamic changes such as any modifications in files will require a full cache purge.', 'breeze' ); ?></p>
76
+ </div>
77
+ </div>
78
+
79
+ <div class="faq-block">
80
+ <h3 class="faq-question"><?php _e( 'Can I exclude URLs of individual files and pages from cache?', 'breeze' ); ?></h3>
81
+ <div class="faq-answer">
82
+ <p><?php _e( 'You can exclude a file by mentioning its URL or file type (by mentioning file extension) in the exclude fields (available in the Breeze settings). Exclude will not let the cache impact that URL or file type.', 'breeze' ); ?></p>
83
+ <p><?php _e( 'If Varnish is active, you will need to exclude URLs and file type(s) in the Varnish configuration. If you are hosting WordPress websites on Cloudways servers, follow ', 'breeze' ); ?>
84
+ <a href="https://support.cloudways.com/how-to-exclude-url-from-varnish/" target="_blank"><?php _e( 'this KB to exclude URLs from the Varnish cache.', 'breeze' ); ?></a>
85
+ </p>
86
+ </div>
87
+ </div>
88
+
89
+ <div class="faq-block">
90
+ <h3 class="faq-question"><?php _e( 'Does it work with all hosting providers?', 'breeze' ); ?></h3>
91
+ <div class="faq-answer">
92
+ <p><?php _e( 'Breeze has been tested to work with all major hosting providers. In addition, major Breeze options such as Gzip, browser cache, minification, grouping, database optimization. CDN integration will work as expected on all hosting providers.', 'breeze' ); ?></p>
93
+ </div>
94
+ </div>
95
+
96
+ <div class="faq-block">
97
+ <h3 class="faq-question"><?php _e( 'Where can I get support for Breeze?', 'breeze' ); ?></h3>
98
+ <div class="faq-answer">
99
+ <p><?php _e( 'You can get your questions answered on the WordPress support forums. If you are a Cloudways customer, please feel free to start a discussion at', 'breeze' ); ?>
100
+ <a href="https://community.cloudways.com/" target="_blank"><?php _e( 'Cloudways Community Forum.', 'breeze' ); ?></a>
101
+ </p>
102
+ </div>
103
+ </div>
104
+
105
+ <div class="faq-block">
106
+ <h3 class="faq-question"><?php _e( 'How can I test and verify the results?', 'breeze' ); ?></h3>
107
+ <div class="faq-answer">
108
+ <p><?php _e( 'You will be able to see the impact of the Breeze Cache Plugin almost immediately. We also recommend using the following tools for generating metrics:', 'breeze' ); ?></p>
109
+ <ul style="margin-top: 10px">
110
+ <li><a href="https://developers.google.com/speed/pagespeed/" target="_blank"><?php _e( 'Google Page Speed', 'breeze' ); ?></a></li>
111
+ <li><a href="https://www.webpagetest.org/test" target="_blank"><?php _e( 'WebPagetest', 'breeze' ); ?></a></li>
112
+ <li><a href="https://tools.pingdom.com/" target="_blank"><?php _e( 'Pingdom', 'breeze' ); ?></a></li>
113
+ </ul>
114
+ </div>
115
+ </div>
116
+
117
+ <div class="faq-block">
118
+ <h3 class="faq-question"><?php _e( 'Does Breeze plugin work with Visual Builder?', 'breeze' ); ?></h3>
119
+ <div class="faq-answer">
120
+ <p><?php _e( 'Yes, Breeze Plugin is compatible with Visual Builder.', 'breeze' ); ?></p>
121
+ </div>
122
+ </div>
123
+
124
+ <div class="faq-block">
125
+ <h3 class="faq-question"><?php _e( 'What popular CDN are supported by Breeze Plugin?', 'breeze' ); ?></h3>
126
+ <div class="faq-answer">
127
+ <p><?php _e( 'Breeze supports the following three popular CDNs:', 'breeze' ); ?></p>
128
+ <ul style="margin-top: 10px">
129
+ <li><a href="https://support.cloudways.com/how-to-use-breeze-with-maxcdn/" target="_blank"><?php _e( 'MaxCDN', 'breeze' ); ?></a></li>
130
+ <li><a href="https://support.cloudways.com/how-to-use-breeze-with-keycdn/" target="_blank"><?php _e( 'KeyCDN', 'breeze' ); ?></a></li>
131
+ <li><a href="https://support.cloudways.com/how-to-use-breeze-with-amazon-cloudfront/" target="_blank"><?php _e( 'Amazon Cloudfront', 'breeze' ); ?></a></li>
132
+ </ul>
133
+ </div>
134
+ </div>
135
+
136
+ <div class="faq-block">
137
+ <h3 class="faq-question"><?php _e( 'Does Breeze support Push CDN?', 'breeze' ); ?></h3>
138
+ <div class="faq-answer">
139
+ <p><?php _e( 'No, Breeze does not support Push CDN. However, you could use Breeze with Push CDNs using third party plugins.', 'breeze' ); ?></p>
140
+ </div>
141
+ </div>
142
+
143
+ <div class="faq-block">
144
+ <h3 class="faq-question"><?php _e( 'Does Breeze Work With CloudFlare?', 'breeze' ); ?></h3>
145
+ <div class="faq-answer">
146
+ <p><?php _e( 'Yes. The process of setting up CloudFlare with Breeze is easy. Check out the following ', 'breeze' ); ?>
147
+ <a href="https://support.cloudways.com/can-i-use-cloudflare-cdn/" target="_blank"><?php _e( 'KnowledgeBase article for details.', 'breeze' ); ?></a>
148
+ </p>
149
+ </div>
150
+ </div>
151
+
152
+ <div class="faq-block">
153
+ <h3 class="faq-question"><?php _e( 'How Breeze cache uses Gzip?', 'breeze' ); ?></h3>
154
+ <div class="faq-answer">
155
+ <p><?php _e( 'Using Gzip, Breeze compresses the request files, further reducing the size of the download files and speeding up the user experience.', 'breeze' ); ?></p>
156
+ </div>
157
+ </div>
158
+ </div>
views/tabs/varnish.php CHANGED
@@ -1,46 +1,46 @@
1
- <?php
2
- defined('ABSPATH') or die;
3
-
4
- $varnish = breeze_get_option( 'varnish_cache', true );
5
- $check_varnish = is_varnish_cache_started();
6
- ?>
7
- <div class="breeze-top-notice">
8
- <p class="breeze_tool_tip"><?php _e('By default Varnish is enabled on all WordPress websites hosted on Cloudways.','breeze')?></p>
9
- </div>
10
- <table cellspacing="15">
11
- <tr>
12
- <td>
13
- <label for="auto-purge-varnish" class="breeze_tool_tip"><?php _e('Auto Purge Varnish', 'breeze'); ?></label>
14
- </td>
15
- <td>
16
- <input type="checkbox" id="auto-purge-varnish" name="auto-purge-varnish" value="1" <?php checked($varnish['auto-purge-varnish'], '1')?>/>
17
- <span class="breeze_tool_tip" ><?php _e('Keep this option enabled to automatically purge Varnish cache on actions like publishing new blog posts, pages and comments.','breeze')?></span>
18
- <br>
19
- <?php if( !$check_varnish): ?>
20
- <span><b>Note:&nbsp;</b>
21
- <span style="color: #ff0000"><?php _e('Seems Varnish is disabled on your Application. Please refer to ', 'breeze') ?><a href="https://support.cloudways.com/most-common-varnish-issues-and-queries/" target="_blank"><?php _e('this KB', 'breeze') ?></a><?php _e(' and learn how to enable it.','breeze') ?> </span>
22
- </span>
23
- <?php endif; ?>
24
- </td>
25
- </tr>
26
- <tr>
27
- <td>
28
- <label for="varnish-server-ip" class="breeze_tool_tip"><?php _e('Varnish server', 'breeze'); ?></label>
29
- </td>
30
- <td>
31
- <input type="text" id="varnish-server-ip" size="20" name="varnish-server-ip"
32
- value='<?php echo(!empty($varnish['breeze-varnish-server-ip']) ? esc_html($varnish['breeze-varnish-server-ip']) : '127.0.0.1'); ?>'/>
33
- <br/>
34
- <span class="breeze_tool_tip"><strong><?php _e('Note: Keep this default if you are a Cloudways customer. Otherwise ask your hosting provider on what to set here.','breeze')?></strong></span>
35
- </td>
36
- </tr>
37
- <tr>
38
- <td style="vertical-align: middle">
39
- <label class="breeze_tool_tip"><?php _e('Purge Varnish Cache', 'breeze'); ?></label>
40
- </td>
41
- <td>
42
- <input type="button" id="purge-varnish-button" class="button" value="<?php _e('Purge','breeze')?>" />
43
- <span style="vertical-align: bottom; margin-left: 5px"><?php _e('Use this option to instantly Purge Varnish Cache on entire website. ', 'breeze') ?></span>
44
- </td>
45
- </tr>
46
- </table>
1
+ <?php
2
+ defined( 'ABSPATH' ) or die;
3
+
4
+ $varnish = breeze_get_option( 'varnish_cache', true );
5
+ $check_varnish = is_varnish_cache_started();
6
+ ?>
7
+ <div class="breeze-top-notice">
8
+ <p class="breeze_tool_tip"><?php _e( 'By default Varnish is enabled on all WordPress websites hosted on Cloudways.', 'breeze' ); ?></p>
9
+ </div>
10
+ <table cellspacing="15">
11
+ <tr>
12
+ <td>
13
+ <label for="auto-purge-varnish" class="breeze_tool_tip"><?php _e( 'Auto Purge Varnish', 'breeze' ); ?></label>
14
+ </td>
15
+ <td>
16
+ <input type="checkbox" id="auto-purge-varnish" name="auto-purge-varnish" value="1" <?php checked( $varnish['auto-purge-varnish'], '1' ); ?>/>
17
+ <span class="breeze_tool_tip" ><?php _e( 'Keep this option enabled to automatically purge Varnish cache on actions like publishing new blog posts, pages and comments.', 'breeze' ); ?></span>
18
+ <br>
19
+ <?php if ( ! $check_varnish ) : ?>
20
+ <span><b>Note:&nbsp;</b>
21
+ <span style="color: #ff0000"><?php _e( 'Seems Varnish is disabled on your Application. Please refer to ', 'breeze' ); ?><a href="https://support.cloudways.com/most-common-varnish-issues-and-queries/" target="_blank"><?php _e( 'this KB', 'breeze' ); ?></a><?php _e( ' and learn how to enable it.', 'breeze' ); ?> </span>
22
+ </span>
23
+ <?php endif; ?>
24
+ </td>
25
+ </tr>
26
+ <tr>
27
+ <td>
28
+ <label for="varnish-server-ip" class="breeze_tool_tip"><?php _e( 'Varnish server', 'breeze' ); ?></label>
29
+ </td>
30
+ <td>
31
+ <input type="text" id="varnish-server-ip" size="20" name="varnish-server-ip"
32
+ value='<?php echo( ! empty( $varnish['breeze-varnish-server-ip'] ) ? esc_html( $varnish['breeze-varnish-server-ip'] ) : '127.0.0.1' ); ?>'/>
33
+ <br/>
34
+ <span class="breeze_tool_tip"><strong><?php _e( 'Note: Keep this default if you are a Cloudways customer. Otherwise ask your hosting provider on what to set here.', 'breeze' ); ?></strong></span>
35
+ </td>
36
+ </tr>
37
+ <tr>
38
+ <td style="vertical-align: middle">
39
+ <label class="breeze_tool_tip"><?php _e( 'Purge Varnish Cache', 'breeze' ); ?></label>
40
+ </td>
41
+ <td>
42
+ <input type="button" id="purge-varnish-button" class="button" value="<?php _e( 'Purge', 'breeze' ); ?>" />
43
+ <span style="vertical-align: bottom; margin-left: 5px"><?php _e( 'Use this option to instantly Purge Varnish Cache on entire website. ', 'breeze' ); ?></span>
44
+ </td>
45
+ </tr>
46
+ </table>