PluginProbe
LWS Optimize – All-in-One Speed Booster & Cache Tools / 1.1
LWS Optimize – All-in-One Speed Booster & Cache Tools v1.1
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 1.1, at lws-optimize.php

1,887 lines 73.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Plugin Name: LWS Optimize
5 * Plugin URI: https://www.lws.fr/
6 * Description: Reach better speed and performances with Optimize! Minification, Combination, Media conversion... Everything you need for a better website
7 * Version: 1.1
8 * Author: LWS
9 * Author URI: https://www.lws.fr
10 * Tested up to: 6.1
11 * Domain Path: /languages
12 *
13 * @link https://sms.lws.fr/
14 * @since 1.0
15 * @package lws-optimize
16 */
17
18 if (!defined('ABSPATH')) {
19 exit; //Exit if accessed directly
20 }
21
22 /**
23 * Load translations, constants, hooks...
24 */
25 add_action('init', 'lws_op_loading');
26 function lws_op_loading()
27 {
28 require_once('classes/CssCombiner.php');
29 require_once('classes/JsCombiner.php');
30 //require_once(plugin_dir_path(__FILE__) . '/vendor/woocommerce/action-scheduler/action-scheduler.php');
31
32 define('LWS_OP_URL', plugin_dir_url(__FILE__));
33 define('LWS_OP_DIR', plugin_dir_path(__FILE__));
34
35 define('LWS_OP_UPLOADS', wp_upload_dir()['basedir'] . '/lws-optimize/');
36 load_plugin_textdomain('lws-optimize', false, dirname(plugin_basename(__FILE__)) . '/languages');
37 }
38
39 function lws_op_cron_schedule($schedules)
40 {
41 $schedules[ 'threeminutes' ] = array( 'interval' => 3 * MINUTE_IN_SECONDS, 'display' => __('3 minutes') );
42 return $schedules;
43 }
44 add_filter('cron_schedules', 'lws_op_cron_schedule');
45
46 /**
47 * Create, if not already existing, a directory for the file-based cache
48 */
49 register_activation_hook(__FILE__, 'lws_op_on_activation');
50 function lws_op_on_activation()
51 {
52 if (!file_exists(wp_upload_dir()['basedir'] . '/lws_optimize')) {
53 @mkdir(wp_upload_dir()['basedir'] . '/lws-optimize', 0755);
54 }
55 }
56
57 /**
58 * Remove the created directory on delete
59 */
60 register_uninstall_hook(__FILE__, 'lws_op_on_delete');
61 function lws_op_on_delete()
62 {
63 rmdir(wp_upload_dir()['basedir'] . '/lws-optimize');
64 }
65
66 register_deactivation_hook(__FILE__, 'lws_op_on_deactivate');
67 function lws_op_on_deactivate()
68 {
69 rmdir(wp_upload_dir()['basedir'] . '/lws-optimize');
70 }
71
72 /**
73 * Enqueue any CSS or JS script needed
74 */
75 add_action('admin_enqueue_scripts', 'lws_op_scripts');
76 function lws_op_scripts()
77 {
78 wp_enqueue_style('lws_op_css', LWS_OP_URL . "css/lws_op_stylesheet.css");
79 }
80
81 /**
82 * Create plugin menu in wp-admin
83 */
84 add_action('admin_menu', 'lws_op_menu_admin');
85 function lws_op_menu_admin()
86 {
87 $menu_slug = 'lws-op-config';
88 add_menu_page(__('LWS Optimize', 'lws-optimize'), 'LWS Optimize', 'read', $menu_slug, 'lws_op_page', LWS_OP_URL . 'images/plugin_lws_optimize.svg');
89 }
90
91
92 ### ALL FUNCTIONS DEDICATED TO THE FRONTEND TAB ###
93 ##
94 ##
95 /**
96 * Minimize HTML to reduce size and improve performances
97 */
98
99 if (get_option('lws_op_min_html')) {
100 add_action('wp_head', 'lws_op_minimize_html');
101 function lws_op_minimize_html()
102 {
103 global $wp;
104 $url = home_url($wp->request);
105 if ($exclude_html = json_decode(get_option('lws_op_exclude_min_html_array'), true)) {
106 if (!in_array($url, $exclude_html)) {
107 ob_start("flhm_wp_html_compression_finish");
108 }
109 } else {
110 ob_start("flhm_wp_html_compression_finish");
111 }
112 }
113 }
114
115 /**
116 * Either minimize, combine or minimize and combine every CSS or JS files into one for reduced download size and better loading speed
117 */
118 if (get_option('lws_op_min_css') || get_option('lws_op_combine_css') || get_option('lws_op_min_js') || get_option('lws_op_combine_js')) {
119 add_action('wp_enqueue_scripts', 'lws_op_print_scripts', 999);
120 function lws_op_print_scripts()
121 {
122 require_once(__DIR__ . '/vendor/autoload.php');
123 global $wp_scripts, $wp_styles;
124 $result = array('scripts' => array(), 'styles' => array());
125 $timestamp = time();
126
127 if (get_option('lws_op_min_css') && get_option('lws_op_combine_css')) {
128 $wp_styles->all_deps($wp_styles->queue);
129 foreach ($wp_styles->to_do as $style) {
130 $result['styles'][$style] = $wp_styles->registered[$style]->src;
131 }
132 $exclude_min_css_tab = get_option('lws_op_exclude_min_css_array') ? json_decode(get_option('lws_op_exclude_min_css_array'), true) : array();
133 $exclude_combine_css_tab = get_option('lws_op_exclude_combine_css_array') ? json_decode(get_option('lws_op_exclude_combine_css_array'), true) : array();
134 $merged_file_location = get_stylesheet_directory() . DIRECTORY_SEPARATOR . 'merged-styles.min.css';
135 $forced_excluded_combined_css = array();
136 $http = is_ssl() ? 'https:' : 'http:';
137 if (file_exists($merged_file_location) && time() - filemtime($merged_file_location) < 129600) {
138 foreach ($result['styles'] as $handle => $style) {
139 if (!empty($style)) {
140 //Check if smth like //domain.com
141 if (!str_contains($style, $http) && str_contains($style, str_replace($http, '', get_site_url()))) {
142 $file = str_replace(str_replace($http, '', get_site_url() . '/'), ABSPATH, $style);
143 }
144 //Check if smth like /wp-includes/.../ + not https://fonts.google...
145 elseif (!str_contains($style, get_site_url()) && !stripos($style, 'fonts.')) {
146 $file = ABSPATH . $style;
147 }
148
149 //Check if smth like https://domain.com
150 elseif (str_contains($style, get_site_url())) {
151 $file = str_replace(get_site_url() . '/', ABSPATH, $style);
152 }
153
154 if (str_contains($file, "./")) {
155 $file = str_replace("./", '', $file);
156 }
157
158 if (str_contains($file, "//")) {
159 $file = str_replace("//", "/", $file);
160 }
161
162 if (file_exists($file) && !in_array($file, $exclude_combine_css_tab) && !in_array($file, $exclude_min_css_tab)) {
163 if (filemtime($merged_file_location) == filemtime($file)) {
164 wp_deregister_style($handle);
165 } else {
166 unlink($merged_file_location);
167 break;
168 }
169 }
170 }
171 }
172 }
173
174 if (!file_exists($merged_file_location)) {
175 $merged_styles = '';
176 $minifierCSS = new \MatthiasMullie\Minify\CSS();
177
178 foreach ($result['styles'] as $handle => $style) {
179 if (!empty($style) && !in_array($handle, $forced_excluded_combined_css)) {
180 if (!str_contains($style, $http) && str_contains($style, str_replace($http, '', get_site_url()))) {
181 $file = str_replace(str_replace($http, '', get_site_url() . '/'), ABSPATH, $style);
182 }
183 //Check if smth like /wp-includes/.../ + not https://fonts.google...
184 elseif (!str_contains($style, get_site_url()) && !stripos($style, 'fonts.')) {
185 $file = ABSPATH . $style;
186 }
187
188 //Check if smth like https://domain.com
189 elseif (str_contains($style, get_site_url())) {
190 $file = str_replace(get_site_url() . '/', ABSPATH, $style);
191 }
192
193 if (str_contains($file, "./")) {
194 $file = str_replace("./", '', $file);
195 }
196
197 if (str_contains($file, "//")) {
198 $file = str_replace("//", "/", $file);
199 }
200
201 if (file_exists($file) && !in_array($file, $exclude_combine_css_tab) && !in_array($file, $exclude_min_css_tab)) {
202 $minifierCSS->add($file);
203 touch($file, $timestamp);
204 }
205
206 wp_deregister_style($handle);
207 }
208 }
209 $minifierCSS->minify($merged_file_location);
210 touch($merged_file_location, $timestamp);
211 }
212 wp_enqueue_style('merged-styles-min', get_stylesheet_directory_uri() . '/merged-styles.min.css');
213 } else {
214 if (get_option('lws_op_min_css')) {
215 $wp_styles->all_deps($wp_styles->queue);
216 foreach ($wp_styles->to_do as $style) {
217 $result['styles'][$style] = $wp_styles->registered[$style]->src;
218 }
219 $exclude_min_css_tab = get_option('lws_op_exclude_min_css_array') ? json_decode(get_option('lws_op_exclude_min_css_array'), true) : array();
220 $http = is_ssl() ? 'https:' : 'http:';
221 foreach ($result['styles'] as $handle => $style) {
222 if (!stripos($style, '.min.css') && !empty($style)) {
223 //Check if smth like //domain.com
224 if (!str_contains($style, $http) && str_contains($style, str_replace($http, '', get_site_url()))) {
225 $file = str_replace(str_replace($http, '', get_site_url() . '/'), ABSPATH, $style);
226 }
227 //Check if smth like /wp-includes/.../ + not https://fonts.google...
228 elseif (!str_contains($style, get_site_url()) && !stripos($style, 'fonts.')) {
229 $file = ABSPATH . $style;
230 }
231
232 //Check if smth like https://domain.com
233 elseif (str_contains($style, get_site_url())) {
234 $file = str_replace(get_site_url() . '/', ABSPATH, $style);
235 }
236
237 if (str_contains($file, "./")) {
238 $file = str_replace("./", '', $file);
239 }
240
241 if (str_contains($file, "//")) {
242 $file = str_replace("//", "/", $file);
243 }
244
245 $file_min = str_replace('.css', '.min.css', $file);
246
247 if (file_exists($file_min) && !in_array($file, $exclude_min_css_tab) && (filemtime($file_min) == filemtime($file))) {
248 $wp_styles->registered[$handle]->src = str_replace('.css', '.min.css', $style);
249 } else {
250 if (!in_array($file, $exclude_min_css_tab)) {
251 $minifierCSS = new \MatthiasMullie\Minify\CSS($file);
252 $minifierCSS->minify($file_min);
253 touch($file, $timestamp);
254 touch($file_min, $timestamp);
255 $wp_styles->registered[$handle]->src = str_replace('.css', '.min.css', $style);
256 }
257 }
258 }
259 }
260 }
261
262 if (get_option('lws_op_combine_css')) {
263 $wp_styles->all_deps($wp_styles->queue);
264 foreach ($wp_styles->to_do as $style) {
265 $result['styles'][$style] = $wp_styles->registered[$style]->src;
266 }
267 $exclude_combine_css_tab = get_option('lws_op_exclude_combine_css_array') ? json_decode(get_option('lws_op_exclude_combine_css_array'), true) : array();
268 $merged_file_location = get_stylesheet_directory() . DIRECTORY_SEPARATOR . 'merged-styles.css';
269 $forced_excluded_combined_css = array();
270 $http = is_ssl() ? 'https:' : 'http:';
271 if (file_exists($merged_file_location) && time() - filemtime($merged_file_location) < 129600) {
272 foreach ($result['styles'] as $handle => $style) {
273 if (!empty($style)) {
274 //Check if smth like //domain.com
275 if (!str_contains($style, $http) && str_contains($style, str_replace($http, '', get_site_url()))) {
276 $file = str_replace(str_replace($http, '', get_site_url() . '/'), ABSPATH, $style);
277 }
278 //Check if smth like /wp-includes/.../ + not https://fonts.google...
279 elseif (!str_contains($style, get_site_url()) && !stripos($style, 'fonts.')) {
280 $file = ABSPATH . $style;
281 }
282
283 //Check if smth like https://domain.com
284 elseif (str_contains($style, get_site_url())) {
285 $file = str_replace(get_site_url() . '/', ABSPATH, $style);
286 }
287
288 if (str_contains($file, "./")) {
289 $file = str_replace("./", '', $file);
290 }
291
292 if (str_contains($file, "//")) {
293 $file = str_replace("//", "/", $file);
294 }
295
296 if (!in_array($handle, $forced_excluded_combined_css) && !in_array($file, $exclude_combine_css_tab)) {
297 if (filemtime($merged_file_location) == filemtime($file)) {
298 wp_deregister_style($handle);
299 } else {
300 unlink($merged_file_location);
301 break;
302 }
303 }
304 }
305 }
306 }
307
308 if (!file_exists($merged_file_location)) {
309 $merged_styles = '';
310
311 foreach ($result['styles'] as $handle => $style) {
312 if (!empty($style) && !in_array($handle, $forced_excluded_combined_css)) {
313 if (!str_contains($style, $http) && str_contains($style, str_replace($http, '', get_site_url()))) {
314 $file = str_replace(str_replace($http, '', get_site_url() . '/'), ABSPATH, $style);
315 }
316 //Check if smth like /wp-includes/.../ + not https://fonts.google...
317 elseif (!str_contains($style, get_site_url()) && !stripos($style, 'fonts.')) {
318 $file = ABSPATH . $style;
319 }
320
321 //Check if smth like https://domain.com
322 elseif (str_contains($style, get_site_url())) {
323 $file = str_replace(get_site_url() . '/', ABSPATH, $style);
324 }
325
326 if (str_contains($file, "./")) {
327 $file = str_replace("./", '', $file);
328 }
329
330 if (file_exists($file) && !in_array($file, $exclude_combine_css_tab)) {
331 $localize = '';
332
333 if (@key_exists('data', $wp_styles->registered[$handle]->extra)) {
334 $localize = $wp_styles->registered[$handle]->extra['data'] . ';';
335 }
336
337 $tmp = file_get_contents($file);
338 $path = explode('/', $file);
339 array_pop($path);
340 $path = implode('/', $path);
341 $path = str_replace(ABSPATH, get_site_url() . '/', $path);
342
343 $tmp = str_replace("url(../", "url(" . $path . "/../", $tmp);
344 $tmp = str_replace("url('../", "url('" . $path . "/../", $tmp);
345 $tmp = str_replace('url("../', 'url("' . $path . "/../", $tmp);
346 $merged_styles .= $localize . $tmp;
347 touch($file, $timestamp);
348 wp_deregister_style($handle);
349 }
350 }
351 }
352 file_put_contents($merged_file_location, $merged_styles);
353 touch($merged_file_location, $timestamp);
354 }
355 wp_enqueue_style('merged-styles', get_stylesheet_directory_uri() . '/merged-styles.css');
356 }
357 }
358
359 if (get_option('lws_op_min_js') && get_option('lws_op_combine_js')) {
360 $wp_scripts->all_deps($wp_scripts->queue);
361 foreach ($wp_scripts->to_do as $script) {
362 $result['scripts'][$script] = $wp_scripts->registered[$script]->src;
363 }
364 $exclude_min_js_tab = get_option('lws_op_exclude_min_js_array') ? json_decode(get_option('lws_op_exclude_min_js_array'), true) : array();
365 $exclude_combine_js_tab = get_option('lws_op_exclude_combine_js_array') ? json_decode(get_option('lws_op_exclude_combine_js_array'), true) : array();
366 $merged_file_location = get_stylesheet_directory() . DIRECTORY_SEPARATOR . 'merged-scripts.min.js';
367 $forced_excluded_combined_js = array();
368 $http = is_ssl() ? 'https:' : 'http:';
369 if (file_exists($merged_file_location) && time() - filemtime($merged_file_location) < 129600) {
370 foreach ($result['scripts'] as $handle => $script) {
371 if (!empty($script)) {
372 //Check if smth like //domain.com
373 if (!str_contains($script, $http) && str_contains($script, str_replace($http, '', get_site_url()))) {
374 $file = str_replace(str_replace($http, '', get_site_url() . '/'), ABSPATH, $script);
375 }
376 //Check if smth like /wp-includes/.../ + not https://fonts.google...
377 elseif (!str_contains($script, get_site_url()) && !stripos($script, 'fonts.')) {
378 $file = ABSPATH . $script;
379 }
380
381 //Check if smth like https://domain.com
382 elseif (str_contains($script, get_site_url())) {
383 $file = str_replace(get_site_url() . '/', ABSPATH, $script);
384 }
385
386 if (str_contains($file, "./")) {
387 $file = str_replace("./", '', $file);
388 }
389
390 if (str_contains($file, "//")) {
391 $file = str_replace("//", "/", $file);
392 }
393
394 if (!in_array($handle, $forced_excluded_combined_js) && !in_array($file, $exclude_combine_js_tab)) {
395 if (filemtime($merged_file_location) == filemtime($file)) {
396 wp_deregister_script($handle);
397 } else {
398 unlink($merged_file_location);
399 break;
400 }
401 }
402 }
403 }
404 }
405
406 if (!file_exists($merged_file_location)) {
407 $merged_scripts = '';
408 $minifierJS = new \MatthiasMullie\Minify\JS();
409
410 foreach ($result['scripts'] as $handle => $script) {
411 if (!empty($script) && !in_array($handle, $forced_excluded_combined_js)) {
412 if (!str_contains($script, $http) && str_contains($script, str_replace($http, '', get_site_url()))) {
413 $file = str_replace(str_replace($http, '', get_site_url() . '/'), ABSPATH, $script);
414 }
415 //Check if smth like /wp-includes/.../ + not https://fonts.google...
416 elseif (!str_contains($script, get_site_url()) && !stripos($script, 'fonts.')) {
417 $file = ABSPATH . $script;
418 }
419
420 //Check if smth like https://domain.com
421 elseif (str_contains($script, get_site_url())) {
422 $file = str_replace(get_site_url() . '/', ABSPATH, $script);
423 }
424
425 if (str_contains($file, "./")) {
426 $file = str_replace("./", '', $file);
427 }
428
429 if (file_exists($file) && !in_array($file, $exclude_combine_js_tab)) {
430 $minifierJS->add($file);
431 touch($file, $timestamp);
432 }
433
434 wp_deregister_script($handle);
435 }
436 }
437 $minifierJS->minify($merged_file_location);
438 touch($merged_file_location, $timestamp);
439 }
440 wp_enqueue_script('merged-scripts-min', get_stylesheet_directory_uri() . '/merged-scripts.min.js');
441 } else {
442 //JS
443 if (get_option('lws_op_min_js')) {
444 $wp_scripts->all_deps($wp_scripts->queue);
445 foreach ($wp_scripts->to_do as $script) {
446 $result['scripts'][$script] = $wp_scripts->registered[$script]->src;
447 }
448 $exclude_min_js_tab = get_option('lws_op_exclude_min_js_array') ? json_decode(get_option('lws_op_exclude_min_js_array'), true) : array();
449 $http = is_ssl() ? 'https:' : 'http:';
450 foreach ($result['scripts'] as $handle => $script) {
451 if (!stripos($script, '.min.js') && !empty($style)) {
452 //Check if smth like //domain.com
453 if (!str_contains($script, $http) && str_contains($script, str_replace($http, '', get_site_url()))) {
454 $file = str_replace(str_replace($http, '', get_site_url() . '/'), ABSPATH, $script);
455 }
456 //Check if smth like /wp-includes/.../ + not https://fonts.google...
457 elseif (!str_contains($script, get_site_url())) {
458 $file = ABSPATH . $script;
459 }
460
461 //Check if smth like https://domain.com
462 elseif (str_contains($script, get_site_url())) {
463 $file = str_replace(get_site_url() . '/', ABSPATH, $script);
464 }
465
466 if (str_contains($file, "./")) {
467 $file = str_replace("./", '', $file);
468 }
469
470 if (str_contains($file, "//")) {
471 $file = str_replace("//", "/", $file);
472 }
473
474 $file_min = str_replace('.js', '.min.js', $file);
475 if (file_exists($file_min) && !in_array($file, $exclude_min_js_tab) && (filemtime($file_min) == filemtime($file))) {
476 $wp_scripts->registered[$handle]->src = str_replace('.js', '.min.js', $script);
477 } else {
478 if (!in_array($file, $exclude_min_js_tab)) {
479 $minifierJS = new \MatthiasMullie\Minify\JS($file);
480 $minifierJS->minify($file_min);
481 $wp_scripts->registered[$handle]->src = str_replace('.js', '.min.js', $script);
482 }
483 }
484 }
485 }
486 }
487
488 if (get_option('lws_op_combine_js')) {
489 $wp_scripts->all_deps($wp_scripts->queue);
490 foreach ($wp_scripts->to_do as $script) {
491 $result['scripts'][$script] = $wp_scripts->registered[$script]->src;
492 }
493 $exclude_combine_js_tab = get_option('lws_op_exclude_combine_js_array') ? json_decode(get_option('lws_op_exclude_combine_js_array'), true) : array();
494 $merged_file_location = get_stylesheet_directory() . DIRECTORY_SEPARATOR . 'merged-scripts.js';
495 $forced_excluded_combined_js = array();
496 $http = is_ssl() ? 'https:' : 'http:';
497 if (file_exists($merged_file_location) && time() - filemtime($merged_file_location) < 129600) {
498 foreach ($result['scripts'] as $handle => $script) {
499 if (!empty($script)) {
500 //Check if smth like //domain.com
501 if (!str_contains($script, $http) && str_contains($script, str_replace($http, '', get_site_url()))) {
502 $file = str_replace(str_replace($http, '', get_site_url() . '/'), ABSPATH, $script);
503 }
504 //Check if smth like /wp-includes/.../ + not https://fonts.google...
505 elseif (!str_contains($script, get_site_url()) && !stripos($script, 'fonts.')) {
506 $file = ABSPATH . $script;
507 }
508
509 //Check if smth like https://domain.com
510 elseif (str_contains($script, get_site_url())) {
511 $file = str_replace(get_site_url() . '/', ABSPATH, $script);
512 }
513
514 if (str_contains($file, "./")) {
515 $file = str_replace("./", '', $file);
516 }
517
518 if (str_contains($file, "//")) {
519 $file = str_replace("//", "/", $file);
520 }
521
522 if (!in_array($handle, $forced_excluded_combined_js) && !in_array($file, $exclude_combine_js_tab)) {
523 if (filemtime($merged_file_location) == filemtime($file)) {
524 wp_deregister_script($handle);
525 } else {
526 unlink($merged_file_location);
527 break;
528 }
529 }
530 }
531 }
532 }
533
534 if (!file_exists($merged_file_location)) {
535 $merged_scripts = '';
536
537 foreach ($result['scripts'] as $handle => $script) {
538 if (!empty($script) && !in_array($handle, $forced_excluded_combined_js)) {
539 if (!str_contains($script, $http) && str_contains($script, str_replace($http, '', get_site_url()))) {
540 $file = str_replace(str_replace($http, '', get_site_url() . '/'), ABSPATH, $script);
541 }
542 //Check if smth like /wp-includes/.../ + not https://fonts.google...
543 elseif (!str_contains($script, get_site_url()) && !stripos($script, 'fonts.')) {
544 $file = ABSPATH . $script;
545 }
546
547 //Check if smth like https://domain.com
548 elseif (str_contains($script, get_site_url())) {
549 $file = str_replace(get_site_url() . '/', ABSPATH, $script);
550 }
551
552 if (str_contains($file, "./")) {
553 $file = str_replace("./", '', $file);
554 }
555
556 if (file_exists($file) && !in_array($file, $exclude_combine_js_tab)) {
557 $localize = '';
558
559 if (@key_exists('data', $wp_scripts->registered[$handle]->extra)) {
560 $localize = $wp_styles->registered[$handle]->extra['data'] . ';';
561 }
562
563 $merged_scripts .= $localize . file_get_contents($file);
564 touch($file, $timestamp);
565 }
566
567 wp_deregister_script($handle);
568 }
569 }
570 file_put_contents($merged_file_location, $merged_scripts);
571 touch($merged_file_location, $timestamp);
572 }
573 wp_enqueue_script('merged-scripts', get_stylesheet_directory_uri() . '/merged-scripts.js', array(), false, false);
574 }
575 }
576 }
577 }
578
579 /**
580 * The loading of all JS scripts is done in parallel of the page loading, making for faster page load time
581 */
582 if (get_option('lws_op_defer_js')) {
583 add_filter('script_loader_tag', 'lws_op_defer_filter', 10, 3);
584 function lws_op_defer_filter($tag, $handle, $src)
585 {
586 if (!is_admin()) {
587 $tag = str_replace('></script>', ' defer></script>', $tag);
588 }
589 return $tag;
590 }
591 }
592
593 /**
594 * Preload all CSS scripts, for faster speed
595 */
596 if (get_option('lws_op_preload_css')) {
597 add_filter('style_loader_tag', 'lws_op_preload_css', 10, 4);
598 function lws_op_preload_css($html, $handle, $href, $media)
599 {
600 if (!is_admin()) {
601 $html = '<link rel="preload" href="' . $href . '" as="style" id="' . $handle . '" media="' . $media . '" onload="this.onload=null;this.rel=\'stylesheet\'">'
602 . '<noscript>' . $html . '</noscript>';
603 }
604 return $html;
605 }
606 }
607
608 /**
609 * Remove the ?ver= query on the CSS/JS files
610 * Can help with caching
611 */
612 if (get_option('lws_op_remove_query')) {
613 add_filter('style_loader_src', 'lws_op_remove_scripts_static', 10);
614 add_filter('script_loader_src', 'lws_op_remove_scripts_static', 10);
615
616 function lws_op_remove_scripts_static($src)
617 {
618 if (strpos($src, '?ver=')) {
619 $src = remove_query_arg('ver', $src);
620 }
621 return $src;
622 }
623 }
624
625 /**
626 * Disable emojis in WordPress => Emojis are still active, but managed by the visitor's browser instead of the server
627 * Better loading time as there is less files to load
628 */
629 if (get_option('lws_op_delete_emoji')) {
630 add_action('init', 'lws_op_disable_emojis');
631 function lws_op_disable_emojis()
632 {
633 remove_action('wp_head', 'print_emoji_detection_script');
634 remove_action('admin_print_scripts', 'print_emoji_detection_script');
635 remove_action('wp_print_styles', 'print_emoji_styles');
636 remove_filter('the_content_feed', 'wp_staticize_emoji');
637 remove_action('admin_print_styles', 'print_emoji_styles');
638 remove_filter('comment_text_rss', 'wp_staticize_emoji');
639 remove_filter('wp_mail', 'wp_staticize_emoji_for_email');
640 add_filter('tiny_mce_plugins', 'lws_op_disable_emojis_tinymce');
641 }
642
643 function lws_op_disable_emojis_tinymce($plugins)
644 {
645 if (is_array($plugins)) {
646 return array_diff($plugins, array('wpemoji'));
647 } else {
648 return array();
649 }
650 }
651 }
652 ##
653 ##
654 ### END OF FRONTEND-RELATED FUNCTIONS ###
655
656
657 ### FUNCTIONS RELATED TO THE MEDIAS TAB ###
658 ##
659 ##
660 /**
661 * Convert all images to JPEG for better size. Duplicate saved as .old to unconvert
662 */
663 function lws_op_compress_all_to_jpeg()
664 {
665 $args = array(
666 'numberposts' => -1,
667 'post_type' => 'attachment',
668 );
669 $attachments = get_posts($args);
670 foreach ($attachments as $a) {
671 if (explode('/', $a->post_mime_type)[0] == 'image') {
672 $metadata = wp_get_attachment_metadata($a->ID);
673 $path = get_attached_file($a->ID);
674 copy($path, $path . '.old');
675 lws_op_compress_to_jpeg($path, $path, 60);
676
677 foreach ($metadata['sizes'] as $size => $data) {
678 $size_path = explode('/', $path);
679 $size_path = implode('/', array_replace($size_path, [(count($size_path) -1) => $data['file']]));
680 copy($size_path, $size_path . '.old');
681 lws_op_compress_to_jpeg($path, $path, 60);
682 }
683 }
684 }
685 }
686
687 /**
688 * Unconvert all images from JPEG to their original type from the .old saved
689 * If there is no original file, do nothing
690 */
691 function lws_op_uncompress_all_to_jpeg()
692 {
693 $args = array(
694 'numberposts' => -1,
695 'post_type' => 'attachment',
696 );
697 $attachments = get_posts($args);
698 foreach ($attachments as $a) {
699 if (explode('/', $a->post_mime_type)[0] == 'image') {
700 $metadata = wp_get_attachment_metadata($a->ID);
701 $path = get_attached_file($a->ID);
702 if (file_exists($path . '.old')) {
703 @rename($path. '.old', $path);
704 // if ($a->post_mime_type == 'image/webp') {
705 // $tmp = explode('.', $path);
706 // array_pop($tmp);
707 // $tmp = implode('.', $tmp);
708 // @rename($tmp. '.old', $tmp);
709 // }
710
711 foreach ($metadata['sizes'] as $size => $data) {
712 $size_path = explode('/', $path);
713 $size_path = implode('/', array_replace($size_path, [(count($size_path) -1) => $data['file']]));
714 @rename($size_path . '.old', $size_path);
715 //if ($a->post_mime_type == 'image/webp') {
716 // $tmp = explode('.', $size_path);
717 // array_pop($tmp);
718 // $tmp = implode('.', $tmp);
719 // @rename($tmp. '.old', $tmp);
720 // }
721 }
722 }
723 }
724 }
725 }
726
727 /**
728 * In charge of converting all the files given to it by lws_op_compress_all_to_jpeg()
729 * The source will be used to create the destination
730 */
731 function lws_op_compress_to_jpeg($source, $destination, $qualite = 60)
732 {
733 $info = getimagesize($source);
734
735 switch($info['mime']) {
736 case 'image/jpeg':
737 $image = imagecreatefromjpeg($source);
738 break;
739 case 'image/gif':
740 $image = imagecreatefromgif($source);
741 break;
742 case 'image/png':
743 $image = imagecreatefrompng($source);
744 break;
745 case 'image/webp':
746 $image = imagecreatefromwebp($source);
747 break;
748 default:
749 $image = imagecreatefromjpeg($source);
750 break;
751 }
752
753 imagejpeg($image, $destination, $qualite);
754
755 return $destination;
756 }
757
758 /**
759 * Given a PATH, create a new WEBP file at the same place
760 * Original files will not be deleted to revert the changes later
761 */
762 function lws_op_generate_webp_file($filepath)
763 {
764 if (!file_exists($filepath)) {
765 return false;
766 }
767
768 // Get image type.
769 $image_type = exif_imagetype($filepath);
770
771 switch ($image_type) {
772 case IMAGETYPE_GIF:
773 $im = imagecreatefromgif($filepath);
774 break;
775 case IMAGETYPE_JPEG:
776 $im = imagecreatefromjpeg($filepath);
777 break;
778 case IMAGETYPE_PNG:
779 $im = imagecreatefrompng($filepath);
780 break;
781 default:
782 return false;
783 }
784
785 $newImagePath = $filepath . '.webp';
786 imagepalettetotruecolor($im);
787 imagealphablending($im, false);
788 imagesavealpha($im, true);
789 imagewebp($im, $newImagePath);
790
791 return $newImagePath;
792 }
793
794 /**
795 * Given a PATH, sizes a name and the original file sizes, create a new WEBP file with a specific size
796 * Original files will not be deleted to revert the changes later
797 */
798 function lws_op_generate_webp_file_sized($filepath, $width, $height, $bw, $bh, $name)
799 {
800 if (!file_exists($filepath)) {
801 return false;
802 }
803
804 // Get image type.
805 $image_type = exif_imagetype($filepath);
806
807 switch ($image_type) {
808 case IMAGETYPE_GIF:
809 $im = imagecreatefromgif($filepath);
810 break;
811 case IMAGETYPE_JPEG:
812 $im = imagecreatefromjpeg($filepath);
813 break;
814 case IMAGETYPE_PNG:
815 $im = imagecreatefrompng($filepath);
816 break;
817 default:
818 return false;
819 }
820
821
822 $newImagePath = $filepath . '.webp';
823 $new_image = imagecreatetruecolor($width, $height);
824
825 imagepalettetotruecolor($im);
826 imagealphablending($im, false);
827 imagesavealpha($im, true);
828
829 imagecopyresampled($new_image, $im, 0, 0, 0, 0, $width, $height, $bw, $bh);
830 imagewebp($im, $newImagePath);
831 return $newImagePath;
832 }
833
834
835 add_action('lws_op_hook_convert_webp', 'lws_op_convert_all_to_webp', 15);
836 add_action('lws_op_hook_unconvert_webp', 'lws_op_delete_webp_files', 8);
837
838
839 /**
840 * Once activated, will convert all current images to WEBP
841 * Original files will not be deleted to revert the changes later
842 */
843 function lws_op_convert_all_to_webp()
844 {
845 global $wpdb;
846 $args = array(
847 'numberposts' => -1,
848 'post_type' => 'attachment',
849 );
850 $attachments = get_posts($args);
851 foreach ($attachments as $a) {
852 if (explode('/', $a->post_mime_type)[0] == 'image' && $a->post_mime_type != 'image/webp') {
853 $id = $a->ID;
854 $metadata = wp_get_attachment_metadata($id);
855 $path = get_attached_file($id);
856 $filename = basename($path);
857 $dirname = dirname($path);
858 @rename($path. '.old', $path);
859
860 if (stripos($filename, '-scaled')) {
861 $name = explode('.', $filename);
862 $name[0] .= '-scaled';
863 $name = implode('.', $name);
864
865 $path = explode('/', $path);
866 array_pop($path);
867 $path[] = $name;
868 $path = implode('/', $path);
869 }
870
871 lws_op_generate_webp_file($path);
872 if (get_option('lws_op_autoconvert_compression')) {
873 copy($path . '.webp', $path . '.webp.old');
874 lws_op_compress_to_jpeg($path . '.webp', $path . '.webp', 60);
875 }
876
877 $base_width = $metadata['width'];
878 $base_height = $metadata['height'];
879 foreach ($metadata['sizes'] as $size => $data) {
880 $old_path = $dirname . '/' . $data['file'];
881 $metadata['sizes'][$size]['file'] = $data['file'] . '.webp';
882 $metadata['sizes'][$size]['mime-type'] = 'image/webp';
883
884 $new_path = explode('/', $path);
885 array_pop($new_path);
886 $new_path[] = $data['file'];
887 $new_path = implode('/', $new_path);
888 lws_op_generate_webp_file_sized($new_path, $data['width'], $data['height'], $base_width, $base_height, $data['file'] . '.webp');
889 if (get_option('lws_op_autoconvert_compression')) {
890 @rename($old_path . '.old', $old_path);
891 copy($old_path . '.webp', $old_path . '.webp.old');
892 lws_op_compress_to_jpeg($old_path . '.webp', $old_path . '.webp', 60);
893 }
894 }
895 $meta_value = $wpdb->get_var($wpdb->prepare(
896 "SELECT meta_value FROM {$wpdb->postmeta} WHERE post_id = %d",
897 $id
898 ));
899 //$wpdb->get_var("SELECT meta_value FROM `{$wpdb->postmeta}` WHERE post_id='{$id}'");
900 wp_update_attachment_metadata($id, $metadata);
901 wp_update_post(array('ID' => $id, 'post_mime_type' => 'image/webp'));
902 $wpdb->query(
903 $wpdb->prepare(
904 "UPDATE {$wpdb->postmeta} SET meta_value = %s WHERE post_id = %d AND meta_key = '_wp_attached_file'",
905 $meta_value . '.webp',
906 $id
907 )
908 );
909 }
910 }
911 lws_op_update_posts_webp("convert");
912 }
913
914 /**
915 * Once activated, will unconvert all current images to their orignal type
916 * If there is no original file, do nothing
917 */
918 function lws_op_delete_webp_files()
919 {
920 global $wpdb;
921 $args = array(
922 'numberposts' => -1,
923 'post_type' => 'attachment',
924 );
925 $attachments = get_posts($args);
926 foreach ($attachments as $a) {
927 if (explode('/', $a->post_mime_type)[0] == 'image' && $a->post_mime_type == 'image/webp') {
928 $id = $a->ID;
929 $metadata = wp_get_attachment_metadata($id);
930 $path = get_attached_file($id);
931 $filename = basename($path);
932 $extension = explode('.', $filename);
933 array_pop($extension);
934
935 $new_path = implode('.', $extension);
936 $extension = end($extension);
937 $dirname = dirname($path);
938 $new_path = $dirname . '/' . $new_path;
939 if (file_exists($new_path)) {
940 @rename($path. '.old', $path);
941 @unlink($path);
942
943 if (get_option('lws_op_autoconvert_compression')) {
944 copy($new_path, $new_path . '.old');
945 lws_op_compress_to_jpeg($new_path, $new_path, 60);
946 }
947
948 foreach ($metadata['sizes'] as $size => $data) {
949 $old_path = $dirname . '/' . $data['file'];
950 $new_name = explode('.', $data['file']);
951 array_pop($new_name);
952 $new_name = implode('.', $new_name);
953 $new_path_size = $dirname . '/' . $new_name;
954 @rename($old_path . '.old', $old_path);
955 @unlink($old_path);
956 $metadata['sizes'][$size]['file'] = $new_name;
957 $metadata['sizes'][$size]['mime-type'] = 'image/' . $extension;
958
959 if (get_option('lws_op_autoconvert_compression')) {
960 copy($new_path_size, $new_path_size. '.old');
961 lws_op_compress_to_jpeg($new_path_size, $new_path_size, 60);
962 }
963 }
964
965 $meta_value = $wpdb->get_var($wpdb->prepare(
966 "SELECT meta_value FROM {$wpdb->postmeta} WHERE post_id = %d",
967 $id
968 ));
969 //$wpdb->get_var("SELECT meta_value FROM `{$wpdb->postmeta}` WHERE post_id='{$id}'");
970 $meta_value = explode('.', $meta_value);
971 array_pop($meta_value);
972 $meta_value = implode('.', $meta_value);
973 wp_update_post(array('ID' => $id, 'post_mime_type' => 'image/' . $extension));
974 wp_update_attachment_metadata($id, $metadata);
975 $wpdb->query(
976 $wpdb->prepare(
977 "UPDATE {$wpdb->postmeta} SET meta_value = %s WHERE post_id = %d AND meta_key = '_wp_attached_file'",
978 $meta_value,
979 $id
980 )
981 );
982 }
983 }
984 }
985 lws_op_update_posts_webp("restore");
986 }
987
988 /**
989 * When a new file is uploaded, if activated, will compress it (if is an image)
990 */
991 if (get_option('lws_op_autoconvert_compression')) {
992 add_filter('wp_generate_attachment_metadata', 'lws_op_compress_to_jpeg_upload', 15, 2);
993 function lws_op_compress_to_jpeg_upload($metadata, $attachment_id)
994 {
995 if (explode('/', reset($metadata['sizes'])['mime-type'])[0] == 'image') {
996 $path = get_attached_file($attachment_id);
997
998 copy($path, $path . '.old');
999 lws_op_compress_to_jpeg($path, $path, 60);
1000
1001 foreach ($metadata['sizes'] as $size => $data) {
1002 $path = explode('/', $path);
1003 array_pop($path);
1004 $path[] = $data['file'];
1005 $path = implode('/', $path);
1006 copy($path, $path . '.old');
1007 lws_op_compress_to_jpeg($path, $path, 60);
1008 }
1009 }
1010 }
1011 }
1012
1013 /**
1014 * When a new file is uploaded, if activated, will convert it to WEBP (if not already)
1015 */
1016 if (get_option('lws_op_autoconvert_webp')) {
1017 add_filter('wp_generate_attachment_metadata', 'lws_op_webp_upload', 10, 2);
1018 function lws_op_webp_upload($metadata, $attachment_id)
1019 {
1020 global $wpdb;
1021
1022 if (explode('/', reset($metadata['sizes'])['mime-type'])[0] == 'image' && reset($metadata['sizes'])['mime-type'] != 'image/webp') {
1023 $meta = $metadata;
1024 $path = get_attached_file($attachment_id);
1025 lws_op_generate_webp_file($path);
1026 $meta['file'] .= '.webp';
1027 foreach ($meta['sizes'] as $size => $data) {
1028 $new_path = explode('/', $path);
1029 array_pop($new_path);
1030 $new_path[] = $data['file'];
1031 $new_path = implode('/', $new_path);
1032 $meta['sizes'][$size]['file'] = $data['file'] . '.webp';
1033 $meta['sizes'][$size]['mime-type'] = "image/webp";
1034 $sizes = wp_get_attachment_image_src($attachment_id, 'full');
1035 lws_op_generate_webp_file_sized($new_path, $data['width'], $data['height'], $sizes[1], $sizes[2], $data['file'] . 'webp');
1036 }
1037
1038 $meta_value = $wpdb->get_var($wpdb->prepare(
1039 "SELECT meta_value FROM {$wpdb->postmeta} WHERE post_id = %d",
1040 $attachment_id
1041 ));
1042 wp_update_post(array('ID' => $attachment_id, 'post_mime_type' => 'image/webp'));
1043 $wpdb->query("UPDATE {$wpdb->postmeta} SET meta_value = '{$meta_value}.webp' WHERE post_id = {$attachment_id} AND meta_key = '_wp_attached_file'");
1044 return $meta;
1045 }
1046
1047 return $metadata;
1048 }
1049 }
1050
1051
1052 /**
1053 * TODO
1054 */
1055 //add_action('delete_attachment', 'lws_op_restore_file_to_default_before_delete');
1056 function lws_op_restore_file_to_default_before_delete($attachment_id, $post)
1057 {
1058 }
1059
1060 function lws_op_update_posts_webp($usage)
1061 {
1062 global $wpdb;
1063 $args = array(
1064 'numberposts' => -1,
1065 'post_type' => 'attachment',
1066 );
1067 $attachments = get_posts($args);
1068 foreach ($attachments as $a) {
1069 if (explode('/', $a->post_mime_type)[0] == 'image') {
1070 $id = $a->ID;
1071 $url = wp_get_attachment_url($id);
1072 if ($usage == "convert") {
1073 $elements = $wpdb->get_results(
1074 $wpdb->prepare(
1075 "UPDATE {$wpdb->posts} SET post_content = REPLACE(post_content, %s, %s)
1076 WHERE post_content LIKE %s
1077 ",
1078 $url . '"',
1079 $url . '.webp"',
1080 '%' . $url . '"%'
1081 )
1082 );
1083 } else {
1084 $url = explode('.', $url);
1085 array_pop($url);
1086 $url = implode('.', $url);
1087 $file = str_replace(get_site_url() . '/', ABSPATH, $url);
1088 if (file_exists($file)) {
1089 $exists = true;
1090 $wpdb->get_results(
1091 $wpdb->prepare(
1092 "UPDATE {$wpdb->posts} SET post_content = REPLACE(post_content, %s, %s)
1093 WHERE post_content LIKE %s
1094 ",
1095 $url . '.webp',
1096 $url,
1097 '%' . $url . '"%'
1098 )
1099 );
1100 }
1101 }
1102
1103 $meta = wp_get_attachment_metadata($id);
1104 foreach ($meta['sizes'] as $key => $size) {
1105 $name = $size['file'];
1106 if ($usage == "convert") {
1107 $name = explode('.', $size['file']);
1108 array_pop($name);
1109 $name = implode('.', $name);
1110
1111 $url = explode('/', wp_get_attachment_url($id));
1112 array_pop($url);
1113 $url[] = $name;
1114 $url = implode('/', $url);
1115
1116 $wpdb->get_results(
1117 $wpdb->prepare(
1118 "UPDATE {$wpdb->posts} SET post_content = REPLACE(post_content, %s, %s)
1119 WHERE post_content LIKE %s
1120 ",
1121 $url . '"',
1122 $url . '.webp"',
1123 '%' . $url . '"%'
1124 )
1125 );
1126 } else {
1127 $url = explode('/', wp_get_attachment_url($id));
1128 array_pop($url);
1129 $url[] = $name;
1130 $url = implode('/', $url);
1131 $file = str_replace(get_site_url() . '/', ABSPATH, $url);
1132 if (file_exists($file)) {
1133 $exists = true;
1134 $wpdb->get_results(
1135 $wpdb->prepare(
1136 "UPDATE {$wpdb->posts} SET post_content = REPLACE(post_content, %s, %s)
1137 WHERE post_content LIKE %s
1138 ",
1139 $url . '.webp',
1140 $url,
1141 '%' . $url . '"%'
1142 )
1143 );
1144 }
1145 }
1146 }
1147 }
1148 }
1149 }
1150 ##
1151 ##
1152 ### END OF MEDIAS-RELATED FUNCTIONS ###
1153
1154 if (get_option('lws_op_force_no_lazyload_video')) {
1155 function lws_op_disable_audio_video_lazy_loading()
1156 {
1157 global $wpdb;
1158
1159 $elements = $wpdb->get_results(
1160 $wpdb->prepare(
1161 "SELECT post_content FROM {$wpdb->posts} WHERE post_content LIKE '%<video%'"
1162 )
1163 );
1164
1165 foreach ($elements as $element) {
1166 $element = $element->post_content;
1167 if (str_contains($element, 'preload="none"')) {
1168 $element = str_replace('preload="none"', 'preload="auto"', $element);
1169 }
1170
1171 $wpdb->get_results(
1172 $wpdb->prepare(
1173 "UPDATE {$wpdb->posts} SET post_content = %s WHERE post_content LIKE '%<video%'",
1174 $element
1175 )
1176 );
1177 }
1178
1179 $elements = $wpdb->get_results(
1180 $wpdb->prepare(
1181 "SELECT post_content FROM {$wpdb->posts} WHERE post_content LIKE '%<audio%'"
1182 )
1183 );
1184
1185 foreach ($elements as $element) {
1186 $element = $element->post_content;
1187 if (str_contains($element, 'preload="none"')) {
1188 $element = str_replace('preload="none"', 'preload="auto"', $element);
1189 }
1190
1191 $wpdb->get_results(
1192 $wpdb->prepare(
1193 "UPDATE {$wpdb->posts} SET post_content = %s WHERE post_content LIKE '%<audio%'",
1194 $element
1195 )
1196 );
1197 }
1198 }
1199 lws_op_disable_audio_video_lazy_loading();
1200 }
1201
1202 if (get_option('lws_op_force_lazyload_video')) {
1203 function lws_op_force_audio_video_lazy_loading()
1204 {
1205 global $wpdb;
1206
1207 $elements = $wpdb->get_results(
1208 $wpdb->prepare(
1209 "SELECT post_content FROM {$wpdb->posts} WHERE post_content LIKE '%<video%'"
1210 )
1211 );
1212
1213 foreach ($elements as $element) {
1214 $element = $element->post_content;
1215 if (str_contains($element, 'autoplay')) {
1216 $element = str_replace('autoplay', '', $element);
1217 }
1218 if (str_contains($element, 'preload="auto"')) {
1219 $element = str_replace('preload="auto"', 'preload="none"', $element);
1220 }
1221 if (str_contains($element, 'preload="metadata"')) {
1222 $element = str_replace('preload="metadata"', 'preload="none"', $element);
1223 }
1224
1225 $wpdb->get_results(
1226 $wpdb->prepare(
1227 "UPDATE {$wpdb->posts} SET post_content = %s WHERE post_content LIKE '%<video%'",
1228 $element
1229 )
1230 );
1231 }
1232
1233 $elements = $wpdb->get_results(
1234 $wpdb->prepare(
1235 "SELECT post_content FROM {$wpdb->posts} WHERE post_content LIKE '%<audio%'"
1236 )
1237 );
1238
1239 foreach ($elements as $element) {
1240 $element = $element->post_content;
1241 if (str_contains($element, 'autoplay')) {
1242 $element = str_replace('autoplay', '', $element);
1243 }
1244 if (str_contains($element, 'preload="auto"')) {
1245 $element = str_replace('preload="auto"', 'preload="none"', $element);
1246 }
1247 if (str_contains($element, 'preload="metadata"')) {
1248 $element = str_replace('preload="metadata"', 'preload="none"', $element);
1249 }
1250
1251 $wpdb->get_results(
1252 $wpdb->prepare(
1253 "UPDATE {$wpdb->posts} SET post_content = %s WHERE post_content LIKE '%<audio%'",
1254 $element
1255 )
1256 );
1257 }
1258 }
1259
1260 lws_op_force_audio_video_lazy_loading();
1261 }
1262
1263 if (get_option('lws_op_deactivate_lazyload')) {
1264 add_filter('wp_lazy_loading_enabled', '__return_false');
1265 wp_die();
1266 }
1267
1268 if (get_option('lws_op_deactivate_lazyload_image')) {
1269 add_filter('wp_lazy_loading_enabled', 'lws_op_disable_image_lazy_loading', 10, 3);
1270 function lws_op_disable_image_lazy_loading($default, $tag_name, $context)
1271 {
1272 if ('img' === $tag_name && 'the_content' === $context) {
1273 return false;
1274 }
1275 return $default;
1276 }
1277 }
1278
1279 if (get_option('lws_op_deactivate_lazyload_iframe')) {
1280 add_filter('wp_lazy_loading_enabled', 'lws_op_disable_iframe_lazy_loading', 10, 3);
1281 //Allows to disable lazy_load on every tags chosen ; here 'iframe' or 'img'
1282 function lws_op_disable_iframe_lazy_loading($default, $tag_name, $context)
1283 {
1284 if ('iframe' === $tag_name && 'the_content' === $context) {
1285 return false;
1286 }
1287 return $default;
1288 }
1289 }
1290
1291 //When file-based caching is activated
1292 if (get_option('lws_op_fb_cache')) {
1293 add_filter('template_include', 'lws_op_fb_tpl_redirect', 1);
1294 function lws_op_fb_tpl_redirect($template)
1295 {
1296 global $wp;
1297 $file = LWS_OP_UPLOADS . $wp->request . '_lws_' . get_current_user_id() . '.html';
1298 $timer = get_option('lws_op_fb_cache');
1299 if (is_file($file) && (time() - filemtime($file)) < $timer) {
1300 return $file;
1301 wp_die();
1302 } else {
1303 ob_start();
1304 add_action('wp_print_footer_scripts', 'lws_op_fb_tpl_redirect_end');
1305 return $template;
1306 }
1307 }
1308
1309 function lws_op_fb_tpl_redirect_end()
1310 {
1311 global $wp;
1312 $file = LWS_OP_UPLOADS . $wp->request . '_lws_' . get_current_user_id() . '.html';
1313 if (!is_file($file)) {
1314 file_put_contents($file, ob_get_contents());
1315 }
1316 }
1317 }
1318
1319 function lws_op_page()
1320 {
1321 global $wp_styles, $wp_scripts, $wpdb;
1322 $frontend_opti_css = array();
1323 $frontend_opti_js = array();
1324 $frontend_opti_html = array();
1325 $tabs_list = array(
1326 array('frontend', __('Frontend', 'lws-optimize')),
1327 array('medias', __('Medias', 'lws-optimize')),
1328 array('caching', __('Caching', 'lws-optimize')),
1329 array('plugins', __('Our plugins', 'lws-optimize')),
1330 );
1331
1332 //FRONTEND//
1333
1334 if (isset($_POST['lws_op_frontend'])) :
1335 $all_options_excluded = array(
1336 'lws_op_exclude_min_css', 'lws_op_exclude_combine_css',
1337 'lws_op_exclude_min_js', 'lws_op_exclude_combine_js', 'lws_op_exclude_defer_js',
1338 'lws_op_exclude_min_html',
1339 );
1340
1341 $all_options = array(
1342 'lws_op_min_css', 'lws_op_combine_css', 'lws_op_preload_css',
1343 'lws_op_min_js', 'lws_op_combine_js', 'lws_op_defer_js',
1344 'lws_op_min_html', 'lws_op_delete_emoji', 'lws_op_remove_query',
1345 );
1346
1347 foreach ($all_options as $option) {
1348 isset($_POST[$option]) ? update_option($option, true) : delete_option($option);
1349 }
1350
1351 foreach ($all_options_excluded as $option) {
1352 if (isset($_POST[$option])) {
1353 $data = sanitize_textarea_field($_POST[$option]);
1354 $data = trim($data);
1355 $data = str_replace(' ', '', $data);
1356
1357 if (!empty($data)) {
1358 $list_data = explode(',', $data);
1359 if ($option == 'lws_op_exclude_min_html') {
1360 foreach ($list_data as $key => $element) {
1361 $list_data[$key] = str_replace(get_site_url() . '/', ABSPATH, $element);
1362 }
1363 } else {
1364 foreach ($list_data as $key => $element) {
1365 $list_data[$key] = ABSPATH . $element;
1366 }
1367 }
1368 update_option($option . '_array', json_encode($list_data, JSON_PRETTY_PRINT));
1369 update_option($option, $data);
1370 } else {
1371 delete_option($option . '_array');
1372 delete_option($option);
1373 }
1374 } else {
1375 delete_option($option . '_array');
1376 delete_option($option);
1377 }
1378 }
1379 endif;
1380
1381
1382 //CSS//
1383
1384 $list_css = array();
1385 foreach ($wp_styles->queue as $handle) {
1386 $element = $wp_styles->registered[$handle]->src;
1387 if (!stripos($element, '.min.css') && !empty($element) && is_string($element)) {
1388 $list_css[] = $element;
1389 }
1390 }
1391
1392 $exclude_min_css_tab = get_option('lws_op_exclude_min_css') ? json_decode(get_option('lws_op_exclude_min_css'), true) : array();
1393 $exclude_combine_css_tab = get_option('lws_op_exclude_combine_css') ? json_decode(get_option('lws_op_exclude_combine_css'), true) : array();
1394
1395 $frontend_opti_css = array(
1396 'min_css' =>
1397 array(
1398 __('Minify your CSS files', 'lws-optimize'),
1399 __('Minify your CSS files to gain performances by reducing their size', 'lws-optimize'),
1400 ),
1401 'exclude_min_css' => __('Choose which files to exclude when minifying CSS files', 'lws-optimize'),
1402 'combine_css' =>
1403 array(
1404 __('Combine CSS files', 'lws-optimize'),
1405 __('Combine CSS files together to reduce HTML queries and gain in performances', 'lws-optimize'),
1406 ),
1407 'exclude_combine_css' => __('Choose which files to ignore when combining CSS files', 'lws-optimize'),
1408 'preload_css' =>
1409 array(
1410 __('Preload CSS files', 'lws-optimize'),
1411 __('Preload CSS files for a faster loading time', 'lws-optimize'),
1412 ),
1413 );
1414
1415
1416 //JS//
1417
1418 $list_js = array();
1419 foreach ($wp_scripts->queue as $handle) {
1420 $element = $wp_scripts->registered[$handle]->src;
1421 if (!stripos($element, '.min.js') && !empty($element) && is_string($element)) {
1422 $list_js[] = $element;
1423 }
1424 }
1425
1426 $frontend_opti_js = array(
1427 'min_js' =>
1428 array(
1429 __('Minify your JS files', 'lws-optimize'),
1430 __('Minify your JS files to gain performances and reduce their size', 'lws-optimize'),
1431 ),
1432 'exclude_min_js' => __('Choose which files to exclude when minifying JS files', 'lws-optimize'),
1433 'combine_js' =>
1434 array(
1435 __('Combine JS files', 'lws-optimize'),
1436 __('Combine JS files to reduce the amount of HTML queries and gain better performances', 'lws-optimize'),
1437 ),
1438 'exclude_combine_js' => __('Choose which files to ignore when combining JS files', 'lws-optimize'),
1439 'defer_js' =>
1440 array(
1441 __('Defer loading of JavaScript files', 'lws-optimize'),
1442 __('Defer loading of JavaScript files for faster loading times', 'lws-optimize'),
1443 ),
1444 'exclude_defer_js' => __('Choose which files to ignore when defering JS files', 'lws-optimize'),
1445 );
1446
1447 //GENERAL HTML//
1448
1449
1450 $frontend_opti_html = array(
1451 'min_html' =>
1452 array(
1453 __('Minify your HTML files', 'lws-optimize'),
1454 __('Minify your HTML files to gain performances and reduce their size', 'lws-optimize'),
1455 ),
1456 'exclude_min_html' => __('Choose which files to exclude when minifying HTML files', 'lws-optimize'),
1457 'delete_emoji' =>
1458 array(
1459 __('Remove Wordpress emoji support from your site', 'lws-optimize'),
1460 __('Remove Wordpress emoji loading to speed up the loading of your website', 'lws-optimize'),
1461 ),
1462 'remove_query' =>
1463 array(
1464 __('Remove useless queries', 'lws-optimize'),
1465 __('Remove useless queries from static files (CSS, JS...), especially "?ver" queries', 'lws-optimize'),
1466 ),
1467 );
1468
1469
1470 //MEDIA
1471
1472 $media_to_webp = array(
1473 'autoconvert_compression' =>
1474 array(
1475 __('Compressing all images', 'lws-optimize'),
1476 __('Compress all images without quality loss to reduce sizes.', 'lws-optimize'),
1477 array(
1478 __('Compress', 'lws-optimize'),
1479 __('Compressed', 'lws-optimize'),
1480 __('Uncompress', 'lws-optimize'),
1481 __('Uncompressed', 'lws-optimize'),
1482 ),
1483 true, //Recommanded
1484 ),
1485 'autoconvert_webp' =>
1486 array(
1487 __('Converting all images to the WEBP extension', 'lws-optimize'),
1488 __('Convert all images to the lightweight WEBP extension to get better loading times. Depending on the amount of files to convert, it may take a while. Restoring the files will re-convert those. You can leave the page will the action in ongoing.', 'lws-optimize'),
1489 array(
1490 __('Convert', 'lws-optimize'),
1491 __('Converted', 'lws-optimize'),
1492 __('Unconvert', 'lws-optimize'),
1493 __('Unconverted', 'lws-optimize'),
1494 ),
1495 true, //Recommanded
1496 ),
1497 'change_max_width_media' =>
1498 array(
1499 __('Reducing the maximum width of an image', 'lws-optimize'),
1500 __('Reduce the maximum width of an image on this website. By default at 2560px, you may want to reduce it, allowing for smaller files, or rise it as you wish.', 'lws-optimize'),
1501 array(
1502 __('Modify', 'lws-optimize'),
1503 __('Modified', 'lws-optimize'),
1504 __('Modify', 'lws-optimize'),
1505 __('Modified', 'lws-optimize'),
1506 ),
1507 false
1508 ),
1509 'deactivate_lazyload_iframe' =>
1510 array(
1511 __('Deactivate lazy loading for all iframe elements', 'lws-optimize'),
1512 false, //No subtext
1513 array(
1514 __('Deactivate', 'lws-optimize'),
1515 __('Deactivated', 'lws-optimize'),
1516 __('Activate', 'lws-optimize'),
1517 __('Activated', 'lws-optimize'),
1518
1519 ),
1520 false,
1521 ),
1522 'deactivate_lazyload_image' =>
1523 array(
1524 __('Deactivate lazy loading for all image elements', 'lws-optimize'),
1525 false,
1526 array(
1527 __('Deactivate', 'lws-optimize'),
1528 __('Deactivated', 'lws-optimize'),
1529 __('Activate', 'lws-optimize'),
1530 __('Activated', 'lws-optimize'),
1531
1532 ),
1533 false,
1534 ),
1535 'deactivate_lazyload' =>
1536 array(
1537 __('Completely deactivate all lazy loading on the website', 'lws-optimize'),
1538 false,
1539 array(
1540 __('Activate', 'lws-optimize'),
1541 __('Activated', 'lws-optimize'),
1542 __('Deactivate', 'lws-optimize'),
1543 __('Deactivated', 'lws-optimize'),
1544 ),
1545 false,
1546 ),
1547 'force_lazyload_video' =>
1548 array(
1549 __('Force preloading of all video and audio elements', 'lws-optimize'),
1550 false,
1551 array(
1552 __('Force', 'lws-optimize'),
1553 __('Forced', 'lws-optimize'),
1554 __('Unforce', 'lws-optimize'),
1555 __('Unforced', 'lws-optimize'),
1556 ),
1557 false,
1558 ),
1559 'force_no_lazyload_video' =>
1560 array(
1561 __('Force deactivation of all preloading of video and audio elements', 'lws-optimize'),
1562 false,
1563 array(
1564 __('Force', 'lws-optimize'),
1565 __('Forced', 'lws-optimize'),
1566 __('Unforce', 'lws-optimize'),
1567 __('Unforced', 'lws-optimize'),
1568 ),
1569 false,
1570 ),
1571 );
1572
1573 get_option('lws_op_change_max_width_media') ? '' : update_option('lws_op_change_max_width_media', '2560');
1574
1575 $list_width = array(
1576 '7680' => '7680px',
1577 '3840' => '3840px',
1578 '2560' => '2560px',
1579 '1920' => '1920px',
1580 '1080' => '1080px',
1581 'disabled' => __('Disabled', 'lws-optimize'),
1582 );
1583
1584 function dir_is_empty($dir)
1585 {
1586 $handle = opendir($dir);
1587 while (false !== ($entry = readdir($handle))) {
1588 if ($entry != "." && $entry != "..") {
1589 closedir($handle);
1590 return false;
1591 }
1592 }
1593 closedir($handle);
1594 return true;
1595 }
1596
1597 $is_cache_empty = dir_is_empty(wp_upload_dir()['basedir'] . "/lws-optimize/");
1598
1599 include __DIR__ . '/views/tabs.php';
1600 }
1601
1602 //AJAX DL Plugin//
1603 add_action("wp_ajax_lws_op_downloadPlugin", "wp_ajax_install_plugin");
1604 //
1605
1606 //AJAX Activate Plugin//
1607 add_action("wp_ajax_lws_op_activatePlugin", "lws_op_activate_plugin");
1608 function lws_op_activate_plugin()
1609 {
1610 if (isset($_POST['ajax_slug'])) {
1611 switch (sanitize_textarea_field($_POST['ajax_slug'])) {
1612 case 'lws-hide-login':
1613 activate_plugin('lws-hide-login/lws-hide-login.php');
1614 break;
1615 case 'lws-sms':
1616 activate_plugin('lws-sms/lws-sms.php');
1617 break;
1618 case 'lws-tools':
1619 activate_plugin('lws-tools/lws-tools.php');
1620 break;
1621 case 'lws-affiliation':
1622 activate_plugin('lws-affiliation/lws-affiliation.php');
1623 break;
1624 case 'lws-cleaner':
1625 activate_plugin('lws-cleaner/lws-cleaner.php');
1626 break;
1627 case 'lwscache':
1628 activate_plugin('lwscache/lwscache.php');
1629 break;
1630 }
1631 }
1632 wp_die();
1633 }
1634 //
1635
1636 ////AJAX EXCLUDE MIN/COMBINE////
1637 add_action("wp_ajax_lws_opti_exclude", "lws_op_exclude");
1638 function lws_op_exclude()
1639 {
1640 if (isset($_POST['data'], $_POST['option'])) {
1641 $list_sites = sanitize_text_field($_POST['data']);
1642 $option = sanitize_text_field($_POST['option']);
1643 update_option($option, $list_sites);
1644
1645 $array = str_replace(' ', '', $list_sites);
1646 $array = explode(',', $array);
1647 if ($option != "lws_op_exclude_min_html") {
1648 foreach ($array as $key => $a) {
1649 $array[$key] = ABSPATH . $a;
1650 }
1651 }
1652 update_option($option . '_array', $array);
1653 }
1654 wp_die();
1655 }
1656
1657 add_action("wp_ajax_lws_add_option_media", "lws_op_add_option");
1658 function lws_op_add_option()
1659 {
1660 if(isset($_POST['action']) && isset($_POST['option'])) {
1661 $option = sanitize_text_field($_POST['option']);
1662 if (isset($_POST['value']) && $option == "lws_op_change_max_width_media") {
1663 $value = sanitize_text_field($_POST['value']);
1664 } else {
1665 $value = true;
1666 }
1667 update_option($option, $value);
1668 if ($option == 'lws_op_autoconvert_webp') {
1669 wp_unschedule_event(wp_next_scheduled('lws_op_hook_unconvert_webp'), 'lws_op_hook_unconvert_webp');
1670 if (! wp_next_scheduled('lws_op_hook_convert_webp')) {
1671 wp_schedule_event(time(), 'threeminutes', 'lws_op_hook_convert_webp');
1672 }
1673 } elseif ($option == 'lws_op_autoconvert_compression') {
1674 lws_op_compress_all_to_jpeg();
1675 }
1676 }
1677 wp_die();
1678 }
1679
1680 add_action("wp_ajax_lws_delete_option_media", "lws_op_delete_option");
1681 function lws_op_delete_option()
1682 {
1683 if(isset($_POST['action']) && isset($_POST['option'])) {
1684 $option = sanitize_text_field($_POST['option']);
1685 delete_option($option);
1686 if ($option == 'lws_op_autoconvert_webp') {
1687 wp_unschedule_event(wp_next_scheduled('lws_op_hook_convert_webp'), 'lws_op_hook_convert_webp');
1688 if (! wp_next_scheduled('lws_op_hook_unconvert_webp')) {
1689 wp_schedule_event(time(), 'threeminutes', 'lws_op_hook_unconvert_webp');
1690 }
1691 } elseif ($option == 'lws_op_autoconvert_compression') {
1692 lws_op_uncompress_all_to_jpeg();
1693 }
1694 }
1695 wp_die();
1696 }
1697
1698 add_action("wp_ajax_lws_opti_max_width_media", "lws_opti_max_width_media");
1699 function lws_opti_max_width_media()
1700 {
1701 if (isset($_POST['value']) && isset($_POST['option'])) {
1702 $value = sanitize_text_field($_POST['value']);
1703 $option = sanitize_text_field($_POST['option']);
1704 update_option($option, $value);
1705 }
1706
1707 wp_die();
1708 }
1709
1710 if (get_option('lws_op_change_max_width_media')) {
1711 $value = get_option('lws_op_change_max_width_media');
1712 if ($value == 'disabled') {
1713 add_filter('big_image_size_threshold', '__return_false');
1714 } else {
1715 add_filter('big_image_size_threshold', 'lws_op_image_size_threshold');
1716 function lws_op_image_size_threshold($threshold)
1717 {
1718 $threshold = get_option('lws_op_change_max_width_media');
1719 return $threshold;
1720 }
1721 }
1722 }
1723
1724 add_action("wp_ajax_lws_optimize_fb_cache", "lws_optimize_fb_cache");
1725 function lws_optimize_fb_cache()
1726 {
1727 if (isset($_POST['action']) && isset($_POST['option'])) {
1728 $timer = ($_POST['timer'] === false) ? sanitize_text_field($_POST['timer']) : '3600';
1729 $option = sanitize_text_field($_POST['option']);
1730 update_option('lws_op_fb_cache', $timer);
1731 } else {
1732 delete_option('lws_op_fb_cache');
1733 }
1734 }
1735
1736 add_action("wp_ajax_lws_no_optimize_fb_cache", "lws_no_optimize_fb_cache");
1737 function lws_no_optimize_fb_cache()
1738 {
1739 if (isset($_POST['action']) && isset($_POST['option'])) {
1740 delete_option('lws_op_fb_cache');
1741 }
1742 }
1743
1744 add_action("wp_ajax_lws_clear_fb_cache", "lws_optimize_clear_cache");
1745 function lws_optimize_clear_cache()
1746 {
1747 array_map('unlink', (glob(wp_upload_dir()['basedir'] . "/lws-optimize/*") ? glob(wp_upload_dir()['basedir'] . "/lws-optimize/*") : array()));
1748 }
1749
1750 add_action("wp_ajax_lws_clear_memcached", "lws_optimize_clear_memcached");
1751 function lws_optimize_clear_memcached()
1752 {
1753 $memcached = new Memcached();
1754 $memcached->addServer('localhost', 11211);
1755 $memcached->flush(1);
1756 }
1757
1758 add_action("wp_ajax_lws_start_memcached", "lws_optimize_start_memcached");
1759 function lws_optimize_start_memcached()
1760 {
1761 if (isset($_POST['action'])) {
1762 update_option('lws_opti_memcaching_on', 1);
1763 file_put_contents(WP_CONTENT_DIR . '/object-cache.php', file_get_contents(LWS_OP_DIR . '/views/object-cache.php'));
1764 }
1765 }
1766
1767 add_action("wp_ajax_lws_stop_memcached", "lws_optimize_stop_memcached");
1768 function lws_optimize_stop_memcached()
1769 {
1770 if (isset($_POST['action'])) {
1771 delete_option('lws_opti_memcaching_on');
1772 unlink(WP_CONTENT_DIR . '/object-cache.php');
1773 }
1774 }
1775
1776
1777 add_action("wp_ajax_lws_restore_webp", "lws_reset_webp_convert");
1778 function lws_reset_webp_convert()
1779 {
1780 wp_unschedule_event(wp_next_scheduled('lws_op_hook_unconvert_webp'), 'lws_op_hook_unconvert_webp');
1781 wp_unschedule_event(wp_next_scheduled('lws_op_hook_convert_webp'), 'lws_op_hook_convert_webp');
1782 do_action('lws_op_hook_unconvert_webp');
1783 do_action('lws_op_hook_convert_webp');
1784 wp_die();
1785 }
1786
1787
1788
1789 /**
1790 * Minify HTML files automatically
1791 * at Zuziko.com
1792 * March 5, 2021 by David Green
1793 */
1794 class FLHM_HTML_Compression
1795 {
1796 protected $flhm_compress_css = true;
1797 protected $flhm_compress_js = true;
1798 protected $flhm_info_comment = true;
1799 protected $flhm_remove_comments = true;
1800 protected $html;
1801 public function __construct($html)
1802 {
1803 if (!empty($html)) {
1804 $this->flhm_parseHTML($html);
1805 }
1806 }
1807 public function __toString()
1808 {
1809 return $this->html;
1810 }
1811 protected function flhm_bottomComment($raw, $compressed)
1812 {
1813 $raw = strlen($raw);
1814 $compressed = strlen($compressed);
1815 $savings = ($raw-$compressed) / $raw * 100;
1816 $savings = round($savings, 2);
1817 return '<!--HTML compressed, size saved '.$savings.'%. From '.$raw.' bytes, now '.$compressed.' bytes-->';
1818 }
1819 protected function flhm_minifyHTML($html)
1820 {
1821 $pattern = '/<(?<script>script).*?<\/script\s*>|<(?<style>style).*?<\/style\s*>|<!(?<comment>--).*?-->|<(?<tag>[\/\w.:-]*)(?:".*?"|\'.*?\'|[^\'">]+)*>|(?<text>((<[^!\/\w.:-])?[^<]*)+)|/si';
1822 preg_match_all($pattern, $html, $matches, PREG_SET_ORDER);
1823 $overriding = false;
1824 $raw_tag = false;
1825 $html = '';
1826 foreach ($matches as $token) {
1827 $tag = (isset($token['tag'])) ? strtolower($token['tag']) : null;
1828 $content = $token[0];
1829 if (is_null($tag)) {
1830 if (!empty($token['script'])) {
1831 $strip = $this->flhm_compress_js;
1832 } elseif (!empty($token['style'])) {
1833 $strip = $this->flhm_compress_css;
1834 } elseif ($content == '<!--wp-html-compression no compression-->') {
1835 $overriding = !$overriding;
1836 continue;
1837 } elseif ($this->flhm_remove_comments) {
1838 if (!$overriding && $raw_tag != 'textarea') {
1839 $content = preg_replace('/<!--(?!\s*(?:\[if [^\]]+]|<!|>))(?:(?!-->).)*-->/s', '', $content);
1840 }
1841 }
1842 } else {
1843 if ($tag == 'pre' || $tag == 'textarea') {
1844 $raw_tag = $tag;
1845 } elseif ($tag == '/pre' || $tag == '/textarea') {
1846 $raw_tag = false;
1847 } else {
1848 if ($raw_tag || $overriding) {
1849 $strip = false;
1850 } else {
1851 $strip = true;
1852 $content = preg_replace('/(\s+)(\w++(?<!\baction|\balt|\bcontent|\bsrc)="")/', '$1', $content);
1853 $content = str_replace(' />', '/>', $content);
1854 }
1855 }
1856 }
1857 if ($strip) {
1858 $content = $this->flhm_removeWhiteSpace($content);
1859 }
1860 $html .= $content;
1861 }
1862 return $html;
1863 }
1864 public function flhm_parseHTML($html)
1865 {
1866 $this->html = $this->flhm_minifyHTML($html);
1867 if ($this->flhm_info_comment) {
1868 $this->html .= "\n" . $this->flhm_bottomComment($html, $this->html);
1869 }
1870 }
1871 protected function flhm_removeWhiteSpace($str)
1872 {
1873 $str = str_replace("\t", ' ', $str);
1874 $str = str_replace("\n", '', $str);
1875 $str = str_replace("\r", '', $str);
1876 $str = str_replace("// The customizer requires postMessage and CORS (if the site is cross domain).", '', $str);
1877 while (stristr($str, ' ')) {
1878 $str = str_replace(' ', ' ', $str);
1879 }
1880 return $str;
1881 }
1882 }
1883 function flhm_wp_html_compression_finish($html)
1884 {
1885 return new FLHM_HTML_Compression($html);
1886 }
1887