PluginProbe
LWS Optimize – All-in-One Speed Booster & Cache Tools / 4.1.4
LWS Optimize – All-in-One Speed Booster & Cache Tools v4.1.4
4.1.4 4.1.3 4.1.2 4.1.1 4.1 4.0 3.4.1 3.4 3.3.21 trunk 1.0 1.1 1.2 1.5 1.6 1.6.5 1.7 1.8 1.8.5 1.8.6 1.9 1.9.1 2.0 2.1 2.1.1 All 97 releases
lws-optimize / lws-optimize.php

lws-optimize.php in LWS Optimize – All-in-One Speed Booster & Cache Tools 4.1.4, at lws-optimize.php

300 lines 12.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 require_once __DIR__ . "/vendor/autoload.php";
3
4 use Lws\Classes\LwsOptimize;
5 use Lws\Classes\LwsOptimizeWpCli;
6 use Lws\Classes\RUM\LwsOptimizeRUM;
7
8 /**
9 * Plugin Name: LWS Optimize - All-in-One Speed Booster & Cache Tools
10 * Plugin URI: https://www.lws.fr/
11 * Description: Reach better speed and performances with Optimize! Minification, Combination, Media convertion... Everything you need for a better website
12 * Version: 4.1.4
13 * Author: LWS
14 * Author URI: https://www.lws.fr
15 * Tested up to: 7.0
16 * Text Domain: lws-optimize
17 * Domain Path: /languages
18 * License: GPL-2.0-or-later
19 *
20 * @link https://www.lws.fr/
21 * @since 1.0
22 * @package lws-optimize
23 *
24 */
25
26 if (!defined('ABSPATH')) {
27 exit;
28 }
29
30
31 // Polyfills of useful PHP8+ functions for PHP < 8
32 if (!function_exists('str_starts_with')) {
33 function str_starts_with($haystack, $needle)
34 {
35 return strlen($needle) === 0 || strpos($haystack, $needle) === 0;
36 }
37 }
38 if (!function_exists('str_contains')) {
39 function str_contains($haystack, $needle)
40 {
41 return strlen($needle) === 0 || strpos($haystack, $needle) !== false;
42 }
43 }
44 if (!function_exists('str_ends_with')) {
45 function str_ends_with($haystack, $needle)
46 {
47 return strlen($needle) === 0 || substr($haystack, -strlen($needle)) === $needle;
48 }
49 }
50
51
52 // https://example.fr/wp-content/plugins/lws-optimize/
53 if (!defined('LWS_OP_URL')) {
54 define('LWS_OP_URL', plugin_dir_url(__FILE__));
55 }
56
57 // ABSPATH/wp-content/plugins/lws-optimize/
58 if (!defined('LWS_OP_DIR')) {
59 define('LWS_OP_DIR', plugin_dir_path(__FILE__));
60 }
61
62 // ABSPATH/wp-content/cache/lwsoptimize/
63 if (!defined('LWS_OP_UPLOADS')) {
64 define('LWS_OP_UPLOADS', WP_CONTENT_DIR . '/cache/lwsoptimize/');
65 }
66
67 // lws-optimize/lws-optimize.php
68 if (!defined('LWS_OP_BASENAME')) {
69 define('LWS_OP_BASENAME', plugin_basename(__FILE__));
70 }
71
72 // Path to the object-cache file (for Memcached)
73 if (!defined('LWSOP_OBJECTCACHE_PATH')) {
74 define('LWSOP_OBJECTCACHE_PATH', WP_CONTENT_DIR . '/object-cache.php');
75 }
76
77
78 // Function declarations for hook callbacks
79 function lwsoptimize_activation_callback() {
80 delete_option('lws_optimize_preload_is_ongoing');
81 LwsOptimizeRUM::create_table();
82
83 $optimize_options = get_option('lws_optimize_config_array', []);
84
85 $GLOBALS['lws_optimize']->lws_optimize_set_cache_htaccess();
86 $GLOBALS['lws_optimize']->lws_optimize_reset_header_htaccess();
87
88 // Deactivate the preloading on plugin activation to prevent issues
89 if (isset($optimize_options['filebased_cache']) && $optimize_options['filebased_cache']['state'] == "true") {
90 // Create the cache directory upfront so a hosting permission issue is caught
91 // (and logged) at activation time instead of surfacing as a silently empty
92 // cache on the first real page view.
93 if (!is_dir(LWS_OP_UPLOADS) && !wp_mkdir_p(LWS_OP_UPLOADS)) {
94 $GLOBALS['lws_optimize']->lwsop_debug_log("LWSOptimize: Could not create cache directory " . LWS_OP_UPLOADS . " on activation");
95 }
96
97 if (wp_next_scheduled("lws_optimize_start_filebased_preload")) {
98 wp_unschedule_event(wp_next_scheduled('lws_optimize_start_filebased_preload'), 'lws_optimize_start_filebased_preload');
99 }
100
101 $optimize_options['filebased_cache']['preload'] = "false";
102 $optimize_options['filebased_cache']['preload_done'] = 0;
103 $optimize_options['filebased_cache']['preload_ongoing'] = "true";
104
105 update_option('lws_optimize_config_array', $optimize_options);
106 }
107
108 wp_unschedule_event(wp_next_scheduled('lws_optimize_convert_media_cron'), 'lws_optimize_convert_media_cron');
109 wp_unschedule_event(wp_next_scheduled('lwsop_revertOptimization'), 'lwsop_revertOptimization');
110
111 if (isset($optimize_options['maintenance_db']) && $optimize_options['maintenance_db']['state'] == "true") {
112 if (wp_next_scheduled("lws_optimize_maintenance_db_weekly")) {
113 wp_unschedule_event(wp_next_scheduled('lws_optimize_maintenance_db_weekly'), 'lws_optimize_maintenance_db_weekly');
114 }
115 wp_schedule_event(time() + 604800, 'weekly', "lws_optimize_maintenance_db_weekly");
116 }
117 }
118
119 function lwsoptimize_deactivation_callback() {
120 delete_option('lws_optimize_preload_is_ongoing');
121
122 // Deactivate all crons
123 wp_unschedule_event(wp_next_scheduled('lws_optimize_start_filebased_preload'), 'lws_optimize_start_filebased_preload');
124 wp_unschedule_event(wp_next_scheduled('lws_optimize_convert_media_cron'), 'lws_optimize_convert_media_cron');
125 wp_unschedule_event(wp_next_scheduled('lws_optimize_maintenance_db_weekly'), 'lws_optimize_maintenance_db_weekly');
126 wp_unschedule_event(wp_next_scheduled("lwsop_revertOptimization"), "lwsop_revertOptimization");
127
128 // Remove the deployed cache-serve script (placed outside /plugins/ to avoid 403s)
129 $deployed_serve = WP_CONTENT_DIR . '/cache/lwsoptimize/lwsop_cache_serve.php';
130 if (file_exists($deployed_serve)) {
131 wp_delete_file($deployed_serve);
132 }
133
134 // Remove .htaccess content
135 $htaccess_file = ABSPATH . '/.htaccess';
136
137 if (file_exists($htaccess_file) && is_writable($htaccess_file)) { // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_is_writable -- runs on (de)activation, before WP_Filesystem credentials would be available
138 $htaccess_content = file_get_contents($htaccess_file);
139
140 // Remove LWS OPTIMIZE - CACHING section
141 $htaccess_content = preg_replace('/\s*#LWS OPTIMIZE - CACHING.*?#END LWS OPTIMIZE - CACHING\s*/s', "\n", $htaccess_content);
142
143 // Remove LWS OPTIMIZE - EXPIRE HEADER section
144 $htaccess_content = preg_replace('/\s*#LWS OPTIMIZE - EXPIRE HEADER.*?#END LWS OPTIMIZE - EXPIRE HEADER\s*/s', "\n", $htaccess_content);
145
146 // Remove LWS OPTIMIZE - GZIP COMPRESSION section
147 $htaccess_content = preg_replace('/\s*#LWS OPTIMIZE - GZIP COMPRESSION.*?#END LWS OPTIMIZE - GZIP COMPRESSION\s*/s', "\n", $htaccess_content);
148
149 // Write the modified content back to the file
150 // phpcs:ignore PluginCheck.CodeAnalysis.WriteFile.ABSPATHDetected -- rewriting the site root .htaccess (which must live at ABSPATH) to remove this plugin's own rules; wp_upload_dir() does not apply here
151 if (isset($GLOBALS['lws_optimize'])) {
152 $GLOBALS['lws_optimize']->lwsop_atomic_write($htaccess_file, $htaccess_content);
153 } else {
154 file_put_contents($htaccess_file, $htaccess_content);
155 }
156 }
157 }
158
159 function lwsoptimize_uninstall_callback() {
160 // Remove the cache folder
161 $cache_dir = WP_CONTENT_DIR . '/cache/lwsoptimize/';
162 $upload_dir = WP_CONTENT_DIR . '/uploads/lwsoptimize/';
163
164 WP_Filesystem();
165 global $wp_filesystem;
166
167 if (file_exists($cache_dir)) {
168 $wp_filesystem->rmdir($cache_dir, true);
169 }
170
171 if (file_exists($upload_dir)) {
172 $wp_filesystem->rmdir($upload_dir, true);
173 }
174
175 // Deactivate all crons
176 wp_unschedule_event(wp_next_scheduled('lws_optimize_start_filebased_preload'), 'lws_optimize_start_filebased_preload');
177 wp_unschedule_event(wp_next_scheduled('lws_optimize_convert_media_cron'), 'lws_optimize_convert_media_cron');
178 wp_unschedule_event(wp_next_scheduled('lws_optimize_maintenance_db_weekly'), 'lws_optimize_maintenance_db_weekly');
179 wp_unschedule_event(wp_next_scheduled("lwsop_revertOptimization"), "lwsop_revertOptimization");
180
181 // Remove .htaccess content
182 $htaccess_file = ABSPATH . '/.htaccess';
183
184 if (file_exists($htaccess_file) && is_writable($htaccess_file)) { // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_is_writable -- runs on (de)activation, before WP_Filesystem credentials would be available
185 $htaccess_content = file_get_contents($htaccess_file);
186
187 // Remove LWS OPTIMIZE - CACHING section
188 $htaccess_content = preg_replace('/\s*#LWS OPTIMIZE - CACHING.*?#END LWS OPTIMIZE - CACHING\s*/s', "\n", $htaccess_content);
189
190 // Remove LWS OPTIMIZE - EXPIRE HEADER section
191 $htaccess_content = preg_replace('/\s*#LWS OPTIMIZE - EXPIRE HEADER.*?#END LWS OPTIMIZE - EXPIRE HEADER\s*/s', "\n", $htaccess_content);
192
193 // Remove LWS OPTIMIZE - GZIP COMPRESSION section
194 $htaccess_content = preg_replace('/\s*#LWS OPTIMIZE - GZIP COMPRESSION.*?#END LWS OPTIMIZE - GZIP COMPRESSION\s*/s', "\n", $htaccess_content);
195
196 // Write the modified content back to the file
197 // phpcs:ignore PluginCheck.CodeAnalysis.WriteFile.ABSPATHDetected -- rewriting the site root .htaccess (which must live at ABSPATH) to remove this plugin's own rules; wp_upload_dir() does not apply here
198 if (isset($GLOBALS['lws_optimize'])) {
199 $GLOBALS['lws_optimize']->lwsop_atomic_write($htaccess_file, $htaccess_content);
200 } else {
201 file_put_contents($htaccess_file, $htaccess_content);
202 }
203 }
204
205 // Remove all options on delete
206 delete_option('lws_optimize_config_array');
207 delete_option('lws_optimize_preload_is_ongoing');
208 delete_option('lws_optimize_image_api_key');
209 delete_option('lws_optimize_cache_statistics');
210 delete_option('lws_optimize_image_conversion_options');
211 delete_option('lwsop_plugin_version');
212 }
213
214 // Actions to execute when the plugin is activated / deactivated / deleted / upgraded
215 register_activation_hook(__FILE__, 'lwsoptimize_activation_callback');
216 register_deactivation_hook(__FILE__, 'lwsoptimize_deactivation_callback');
217 register_uninstall_hook(__FILE__, 'lwsoptimize_uninstall_callback');
218
219 add_action('plugins_loaded', function() {
220 $ancienne_version = get_option('lwsop_plugin_version', 0);
221 $nouvelle_version = '3.3.11'; // Remplacez par la version actuelle du plugin.
222
223 if ($ancienne_version !== $nouvelle_version) {
224 add_option( 'wp_lwsoptimize_post_update', 1);
225 LwsOptimizeRUM::create_table();
226
227 // Mettre à jour la version en base.
228 update_option('lwsop_plugin_version', $nouvelle_version);
229 }
230 });
231
232 // Manage the "Our plugins" tab, allowing users to install our plugins
233 add_action("wp_ajax_lws_op_downloadPlugin", "wp_ajax_install_plugin");
234 add_action("wp_ajax_lws_op_activatePlugin", function()
235 {
236 check_ajax_referer('activate_plugin', '_ajax_nonce');
237 if (!current_user_can('activate_plugins')) {
238 wp_send_json_error(['code' => 'FORBIDDEN'], 403);
239 }
240 if (isset($_POST['ajax_slug'])) {
241 switch (sanitize_textarea_field(wp_unslash($_POST['ajax_slug']))) {
242 case 'lws-hide-login':
243 activate_plugin('lws-hide-login/lws-hide-login.php');
244 break;
245 case 'lws-tools':
246 activate_plugin('lws-tools/lws-tools.php');
247 break;
248 case 'lws-affiliation':
249 activate_plugin('lws-affiliation/lws-affiliation.php');
250 break;
251 case 'lws-cleaner':
252 activate_plugin('lws-cleaner/lws-cleaner.php');
253 break;
254 default:
255 break;
256 }
257 }
258 });
259
260 $lwsoptimize_deactivated = get_option('lws_optimize_deactivate_temporarily', false);
261 if ($lwsoptimize_deactivated) {
262 if (time() > $lwsoptimize_deactivated) {
263 delete_option('lws_optimize_deactivate_temporarily');
264 }
265 }
266
267 // PHP-level compression fallback for shared-hosting vhosts where mod_deflate/
268 // mod_brotli aren't loaded, so the "GZIP/Brotli" toggle isn't a no-op there (see
269 // LwsOptimize::lwsop_check_apache_compression_support()). This must be opened here,
270 // before LwsOptimize's constructor starts the file-cache output buffer below, so it
271 // wraps AROUND that buffer: it only affects the bytes sent to the browser, never
272 // what gets written to the HTML cache.
273 if (
274 function_exists('ob_gzhandler')
275 // Set by lwsop_check_apache_compression_support(): that probe measures whether
276 // Apache itself compresses, so this fallback must stay out of its way or it would
277 // report "supported" on a server whose compression modules aren't even loaded.
278 && !isset($_SERVER['HTTP_X_LWSOP_COMPRESSION_PROBE'])
279 && !is_admin()
280 && !(defined('DOING_CRON') && DOING_CRON)
281 && !(defined('DOING_AJAX') && DOING_AJAX)
282 && !(defined('REST_REQUEST') && REST_REQUEST)
283 && !(defined('WP_CLI') && WP_CLI)
284 ) {
285 $lwsop_bootstrap_options = get_option('lws_optimize_config_array', []);
286 $lwsop_gzip_enabled = ($lwsop_bootstrap_options['gzip_compression']['state'] ?? 'false') === 'true';
287 $lwsop_apache_compression_missing = get_option('lwsop_apache_compression_detected', 'true') === 'false';
288 if ($lwsop_gzip_enabled && $lwsop_apache_compression_missing) {
289 ob_start('ob_gzhandler');
290 }
291 unset($lwsop_bootstrap_options, $lwsop_gzip_enabled, $lwsop_apache_compression_missing);
292 }
293
294 $GLOBALS['lws_optimize'] = new LwsOptimize();
295
296 // Register WP-CLI commands once the plugin is loaded
297 if (defined('WP_CLI') && WP_CLI) {
298 LwsOptimizeWpCli::register_commands();
299 }
300