PluginProbe ʕ •ᴥ•ʔ
10Web Booster – Website speed optimization, Cache & Page Speed optimizer / trunk
10Web Booster – Website speed optimization, Cache & Page Speed optimizer vtrunk
2.33.0 2.30.5 2.30.7 2.30.9 2.31.10 2.31.8 2.32.11 2.32.21 2.32.3 2.32.4 2.32.7 2.6.31 2.6.40 2.6.42 2.6.7 2.7.37 2.7.44 2.7.47 2.8.18 2.8.19 2.8.32 2.8.34 2.8.35 2.9.23 2.9.24 2.9.25 2.9.27 v2.27.4 trunk 2.0.10 2.0.11 2.0.12 2.0.13 2.0.14 2.0.15 2.0.17 2.0.18 2.0.21 2.0.22 2.0.25 2.0.26 2.0.27 2.0.3 2.0.7 2.0.9 2.10.46 2.10.65 2.10.66 2.10.68 2.11.41 2.11.42 2.11.43 2.12.15 2.12.21 2.12.22 2.12.23 2.12.26 2.13.37 2.13.40 2.13.41 2.13.42 2.13.44 2.13.45 2.13.47 2.14.49 2.14.50 2.15.18 2.17.21 2.17.23 2.18.17 2.19.44 2.19.45 2.19.46 2.19.49 2.2.12 2.2.15 2.2.16 2.2.18 2.2.8 2.20.31 2.20.32 2.20.33 2.21.11 2.21.12 2.21.16 2.21.25 2.22.32 2.23.13 2.23.15 2.23.16 2.23.18 2.24.12 2.24.14 2.24.18 2.25.14 2.26.6 2.28.10 2.28.13 2.28.14 2.28.7 2.29.1 2.29.2 2.29.3 2.3.0 2.3.1 2.3.2 2.3.3 2.30.18
tenweb-speed-optimizer / includes / OptimizerMain.php
tenweb-speed-optimizer / includes Last commit date
WebPageCache 7 months ago external 2 months ago ExcludeJsFromDelay.php 2 years ago OptimizerBanner.php 11 months ago OptimizerBase.php 2 years ago OptimizerCSSMin.php 2 years ago OptimizerCache.php 1 year ago OptimizerCacheStructure.php 2 years ago OptimizerCriticalCss.php 1 year ago OptimizerElementor.php 2 years ago OptimizerFonts.php 2 years ago OptimizerImages.php 1 year ago OptimizerLogger.php 1 year ago OptimizerMain.php 2 months ago OptimizerOnInit.php 11 months ago OptimizerScripts.php 2 years ago OptimizerSettings.php 2 months ago OptimizerStyles.php 2 years ago OptimizerUrl.php 1 year ago OptimizerUtils.php 2 months ago OptimizerWhiteLabel.php 2 years ago
OptimizerMain.php
1243 lines
1 <?php
2
3 namespace TenWebOptimizer;
4
5 use DiDom\Exceptions\InvalidSelectorException;
6 use JSMin\JSMin;
7
8 class OptimizerMain
9 {
10 protected static $instance = null;
11
12 private $is_testing = false;
13
14 private $tenweb_handle;
15
16 private $two_delay_js_execution = false;
17
18 private $two_delay_all_js_execution = false;
19
20 private $two_timeout_js_load = false;
21
22 private $two_delay_js_exclusions = null;
23
24 private $two_exclude_js = '';
25
26 private $two_load_excluded_js_normally = '';
27
28 private $two_exclude_delay_js = [];
29
30 private $two_disabled_delay_all_js_pages = [];
31
32 private $two_exclude_css = '';
33
34 private $two_include_inline_js = '';
35
36 private $two_include_inline_css = '';
37
38 private $two_dequeue_jquery_migrate = '';
39
40 private $current_url = null;
41
42 private $async_all = false;
43
44 private $aggregate_js = false;
45
46 private $aggregate_css = false;
47
48 private $two_do_not_optimize_images = 'off';
49
50 private $two_lazyload = 'off';
51
52 private $two_add_noscript = 'off';
53
54 private $two_bg_lazyload = 'off';
55
56 private $two_enable_use_srcset = 'off';
57
58 private $two_enable_picture_webp_delivery = 'off';
59
60 private $two_video_lazyload = 'off';
61
62 private $two_iframe_lazyload = 'off';
63
64 private $two_delay_iframe_lazyload = 'off';
65
66 private $two_elemrntor_video_iframe = 'off';
67
68 private $two_youtube_vimeo_iframe_lazyload = 'off';
69
70 private $two_gzip = false;
71
72 private $browser_lazy = false;
73
74 private $vanilla_lazy = false;
75
76 /**
77 * @var mixed|void
78 */
79 private $two_delayed_js_execution_list;
80
81 /**
82 * @var OptimizerCacheStructure
83 */
84 private $cacheStructure;
85
86 private $TwoSettings;
87
88 private $use_extended_exception_list_js;
89
90 /**
91 * @var string
92 */
93 private $two_delayed_js_load_libs_first;
94
95 private $critical;
96
97 private $two_webp_delivery_working = false;
98
99 private $ao_imgopt = null;
100
101 private $elementor_youtube_video = false;
102
103 /**
104 * @var false|mixed|string|null
105 */
106 public $two_test_mode;
107
108 /**
109 * @var false|mixed|string|null
110 */
111 public $two_minify_html;
112
113 /**
114 * @var bool
115 */
116 public $minify_js;
117
118 /**
119 * @var bool
120 */
121 public $minify_css;
122
123 /**
124 * @var bool
125 */
126 private $page_has_id = true;
127
128 private function __construct()
129 {
130 @ini_set('pcre.backtrack_limit', 5000000); // phpcs:ignore
131 @ini_set('pcre.recursion_limit', 5000000); // phpcs:ignore
132
133 add_action('elementor/widget/render_content', [$this, 'detect_elementor_video_widget'], 10, 2);
134 add_action('send_headers', [ $this, 'two_headers' ]);
135 do_action('wp_meta');
136 global $TwoSettings;
137 $this->two_webp_delivery_working = $TwoSettings->get_settings('two_webp_delivery_working');
138 // Move the initialization to wp action to have wp query already set as we need to identify the search pages.
139 // Set the priority to the end to avoid conflicts with third party plugins.
140 add_action('wp', [ $this, 'init' ], PHP_INT_MAX - 1);
141 }
142
143 public static function get_instance()
144 {
145 if (null == self::$instance) {
146 self::$instance = new self();
147 }
148
149 return self::$instance;
150 }
151
152 public function init()
153 {
154 OptimizerUtils::download_critical();
155
156 if (!defined('TWO_CACHE_DIR')) {
157 define('TWO_CACHE_DIR', OptimizerCache::get_path());
158 }
159 global $TwoSettings;
160 $this->TwoSettings = $TwoSettings;
161 $lazy_load_type = $this->TwoSettings->get_settings('lazy_load_type');
162 $this->is_testing = $this->TwoSettings->getTestMode();
163
164 if ($lazy_load_type === 'browser') {
165 $this->browser_lazy = true;
166 }
167
168 if ($lazy_load_type === 'vanilla') {
169 $this->vanilla_lazy = true;
170 }
171 $this->two_do_not_optimize_images = $this->TwoSettings->get_settings('two_do_not_optimize_images');
172 $this->two_enable_use_srcset = $this->TwoSettings->get_settings('two_enable_use_srcset');
173 $this->two_enable_picture_webp_delivery = $this->TwoSettings->get_settings('two_enable_picture_webp_delivery');
174 $this->two_lazyload = $this->TwoSettings->get_settings('two_lazyload');
175 $this->two_add_noscript = $this->TwoSettings->get_settings('two_add_noscript');
176 $this->two_bg_lazyload = $this->TwoSettings->get_settings('two_bg_lazyload');
177
178 if ($this->two_bg_lazyload !== 'on') {
179 $this->two_bg_lazyload = $this->TwoSettings->get_settings('two_img_in_viewport_lazyload');
180 }
181 $this->two_video_lazyload = $this->TwoSettings->get_settings('two_video_lazyload');
182 $this->two_iframe_lazyload = $this->TwoSettings->get_settings('two_iframe_lazyload');
183 $this->two_delay_iframe_lazyload = $this->TwoSettings->get_settings('two_delay_iframe_lazyload');
184 $this->two_elemrntor_video_iframe = $this->TwoSettings->get_settings('two_elemrntor_video_iframe');
185 $this->two_youtube_vimeo_iframe_lazyload = $this->TwoSettings->get_settings('two_youtube_vimeo_iframe_lazyload');
186 $this->two_gzip = $this->TwoSettings->get_settings('two_gzip');
187 $this->aggregate_js = empty($this->TwoSettings->get_settings('two_aggregate_js', false)) ? false : true;
188 $this->aggregate_css = empty($this->TwoSettings->get_settings('two_aggregate_css', false)) ? false : true;
189 $this->two_delay_js_execution = empty($this->TwoSettings->get_settings('two_delay_js_execution', false)) ? false : true;
190 $this->two_delay_all_js_execution = empty($this->TwoSettings->get_settings('two_delay_all_js_execution', false)) ? false : true;
191
192 if ($this->two_delay_all_js_execution) {
193 $builder_type = OptimizerUtils::detect_builder_type();
194
195 if ($builder_type === 'wvc') {
196 $this->TwoSettings->update_setting('two_delay_all_js_execution', '', false);
197 $this->two_delay_all_js_execution = false;
198 }
199 }
200 $this->two_timeout_js_load = $this->TwoSettings->get_settings('two_timeout_js_load', false) === 'on';
201 $this->two_delay_js_exclusions = $TwoSettings->get_settings('two_delay_js_exclusions', false);
202 $this->two_test_mode = $this->TwoSettings->get_settings('two_test_mode');
203 $this->two_minify_html = $this->TwoSettings->get_settings('two_minify_html');
204
205 $this->minify_js = empty($this->TwoSettings->get_settings('two_minify_js', false)) ? false : true;
206 $this->minify_css = empty($this->TwoSettings->get_settings('two_minify_css', false)) ? false : true;
207
208 $this->use_extended_exception_list_js = empty($this->TwoSettings->get_settings('two_use_extended_exception_list_js', false)) ? false : true;
209 $two_generate_ccss_on_load = $TwoSettings->get_settings('two_generate_ccss_on_load');
210 $two_generate_ccss_on_load_types = is_array($two_generate_ccss_on_load) ? $two_generate_ccss_on_load : [];
211
212 $this->current_url = OptimizerUtils::get_page_url();
213
214 $dir = OptimizerCache::get_path();
215
216 if (OptimizerUtils::dirsize($dir) > TENWEB_CACHE_ALLOWED_DIR_SIZE_IN_BYTES) { // 1Gb
217 $this->clear_cache(false, false, true, true, 'front_page', false, true, true, true);
218 }
219
220 $this->cacheStructure = OptimizerCacheStructure::init();
221
222 global $post;
223 $post_mode = '';
224
225 if (isset($post) && isset($post->ID)) {
226 $post_mode = get_post_meta($post->ID, 'two_mode', true);
227 }
228 $two_default_mode = get_option('two_default_mode');
229
230 if (TENWEB_SO_HOSTED_ON_10WEB && !is_array($two_default_mode) && !isset($_GET['mode']) && !wp_doing_ajax()) { // phpcs:ignore
231 OptimizerUtils::set_global_mode();
232 }
233
234 $should_serve_optimized_page = $this->should_serve_optimized_page($post_mode);
235
236 if ($should_serve_optimized_page === true) {
237 /*Check if user free and not critical page ont optimize */
238 $request_url = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http') . '://' . sanitize_url($_SERVER['HTTP_HOST']) . sanitize_url($_SERVER['REQUEST_URI']); // phpcs:ignore
239 $home_url = rtrim(get_home_url(), '/');
240 $page_url = rtrim($request_url, '/');
241 $critical_page_id = null;
242
243 if ($home_url === $page_url) {
244 $critical_page_id = 'front_page';
245 }
246 $this->critical = new OptimizerCriticalCss($critical_page_id);
247 global $tenweb_subscription_id;
248 $tenweb_subscription_id = (int) $tenweb_subscription_id;
249 $page_id = $this->critical->page_id;
250
251 if (strpos($page_id, 'no_critical') === 0) {
252 $this->page_has_id = false;
253 }
254
255 if (empty($page_id)) {
256 self::add_optimization_status_headers(0, 'Page id not found');
257
258 return;
259 }
260 $page_mode = OptimizerUrl::getPageModeByID($page_id);
261 $id = $page_mode[ 'id' ];
262 $type = $page_mode[ 'type' ];
263 $page_mode = $page_mode[ 'page_mode' ];
264 $post_type = get_post_type($page_id);
265
266 $conditions_for_generating_ccss = false;
267
268 if ((in_array('page', $two_generate_ccss_on_load_types) && $post_type == 'page')
269 || (in_array('post', $two_generate_ccss_on_load_types) && $post_type == 'post')) {
270 $conditions_for_generating_ccss = true;
271 } elseif (in_array('taxonomy', $two_generate_ccss_on_load_types) && str_contains($page_id, 'term_')) {
272 $conditions_for_generating_ccss = true;
273 }
274
275 if (in_array((int) $tenweb_subscription_id, TENWEB_SO_FREE_SUBSCRIPTION_IDS) && $page_id != 'front_page' && !is_array($page_mode)) {
276 if (isset($this->critical->two_critical_pages[$page_id]['status']) && $this->critical->two_critical_pages[$page_id]['status'] != 'success' && $this->critical->two_critical_pages[$page_id]['status'] != 'in_progress') {
277 if ($this->page_has_id) {
278 OptimizerCriticalCss::generate_critical_css_by_id($page_id);
279 }
280 self::add_optimization_status_headers(0, 'Critical id not found');
281
282 return;
283 }
284
285 if (!isset($this->critical->critical_css)) {
286 self::add_optimization_status_headers(0, 'Critical id not found');
287
288 return;
289 }
290 } elseif (TWO_ALWAYS_CRITICAL && !TENWEB_SO_HOSTED_ON_10WEB &&
291 (!isset($this->critical->two_critical_pages) || !isset($this->critical->two_critical_pages[$page_id])
292 || $this->critical->two_critical_pages[$page_id]['status'] === 'not_started')) {
293 if ($page_id === 'front_page' || $conditions_for_generating_ccss) {
294 $two_flow_critical_start = get_option('two_flow_critical_start');
295
296 if ($two_flow_critical_start === '1' && \Tenweb_Authorization\Login::get_instance()->check_logged_in()) {
297 if ($this->page_has_id) {
298 OptimizerCriticalCss::generate_critical_css_by_id($page_id);
299 }
300 }
301 }
302 } elseif (TENWEB_SO_HOSTED_ON_10WEB
303 && (
304 (!isset($this->critical->two_critical_pages) || !isset($this->critical->two_critical_pages[$page_id]))
305 || ($this->critical->two_critical_pages[$page_id]['status'] != 'success'
306 && $this->critical->two_critical_pages[$page_id]['status'] != 'in_progress')
307 )
308 && $conditions_for_generating_ccss) {
309 if ($this->page_has_id) {
310 OptimizerCriticalCss::generate_critical_css_by_id($page_id);
311 }
312 }
313 $date = time();
314
315 if ($page_id === 'front_page') {
316 update_option('two_optimized_date_front_page', $date, false);
317 } elseif ('term_' == $type) {
318 update_term_meta($id, 'two_optimized_date', $date);
319 } elseif ('user_' == $type) {
320 update_user_meta($id, 'two_optimized_date', $date);
321 } else {
322 update_post_meta($page_id, 'two_optimized_date', $date);
323 }
324
325 OptimizerUtils::init_defines();
326 $this->check_cache_dir(OptimizerCache::get_path());
327 $two_delayed_js_execution_list = $this->TwoSettings->get_settings('two_delayed_js_execution_list');
328 $two_exclude_js = $this->TwoSettings->get_settings('two_exclude_js');
329 $two_load_excluded_js_normally = $this->TwoSettings->get_settings('two_load_excluded_js_normally');
330 $two_exclude_delay_js = $this->TwoSettings->get_settings('two_exclude_delay_js');
331 $two_disabled_delay_all_js_pages = $this->TwoSettings->get_settings('two_disabled_delay_all_js_pages');
332 $two_delayed_js_load_libs_first = $this->TwoSettings->get_settings('two_delayed_js_load_libs_first');
333 $two_exclude_css = $this->TwoSettings->get_settings('two_exclude_css');
334 $two_include_inline_js = $this->TwoSettings->get_settings('two_include_inline_js');
335 $two_include_inline_css = $this->TwoSettings->get_settings('two_include_inline_css');
336 $two_dequeue_jquery_migrate = $this->TwoSettings->get_settings('two_dequeue_jquery_migrate');
337 $async_all = $this->TwoSettings->get_settings('two_async_all');
338 $two_disable_wp_dashicons = $this->TwoSettings->get_settings('two_disable_wp_dashicons');
339
340 if ($two_delayed_js_execution_list != false) {
341 $this->two_delayed_js_execution_list = $two_delayed_js_execution_list;
342 }
343
344 if ($two_exclude_js != false) {
345 $this->two_exclude_js = $two_exclude_js;
346 }
347
348 if ($two_load_excluded_js_normally != false) {
349 $this->two_load_excluded_js_normally = $two_load_excluded_js_normally;
350 }
351
352 if (!empty($two_exclude_delay_js)) {
353 $this->two_exclude_delay_js = explode(',', $two_exclude_delay_js);
354 }
355
356 if (!empty($two_disabled_delay_all_js_pages)) {
357 $this->two_disabled_delay_all_js_pages = $two_disabled_delay_all_js_pages;
358 $two_disabled_delay_all_js_pages_arr = array_filter(
359 array_map('trim', explode(',', $this->two_disabled_delay_all_js_pages))
360 );
361
362 foreach ($two_disabled_delay_all_js_pages_arr as $optimizerDisabledPage) {
363 if (preg_match('~' . $optimizerDisabledPage . '~', $_SERVER['REQUEST_URI'])) { // phpcs:ignore
364 $this->two_delay_all_js_execution = false;
365 }
366 }
367 }
368
369 if ($two_exclude_css != false) {
370 $this->two_exclude_css = $two_exclude_css;
371 }
372
373 if ($async_all === 'on') {
374 $this->async_all = true;
375 }
376
377 if ($two_include_inline_js != false) {
378 $this->two_include_inline_js = 'on';
379 }
380
381 if ($two_include_inline_css != false) {
382 $this->two_include_inline_css = 'on';
383 }
384
385 if ($two_delayed_js_load_libs_first != false) {
386 $this->two_delayed_js_load_libs_first = 'on';
387 }
388
389 if ($two_dequeue_jquery_migrate != false) {
390 $this->two_dequeue_jquery_migrate = 'on';
391 }
392
393 $this->check_and_create_dirs();
394
395 // Fix Elementor slideshow background before delayed js are loaded.
396 add_action('elementor/frontend/before_render', function ($element) {
397 if ('slideshow' == $element->get_settings('background_background')) {
398 if (!empty($element->get_settings('background_slideshow_gallery')[0]['url'])) {
399 $element->add_render_attribute(
400 '_wrapper',
401 [
402 'style' => 'background: url("' . $element->get_settings('background_slideshow_gallery')[ 0 ][ 'url' ] . '") ' . (!empty($element->get_settings('background_slideshow_background_position')) ? $element->get_settings('background_slideshow_background_position') : 'center') . '/' . (!empty($element->get_settings('background_slideshow_background_size')) ? $element->get_settings('background_slideshow_background_size') : 'cover'),
403 ]
404 );
405 }
406 }
407 });
408
409 // We need to remove default WP lazyloading as it conflicts with vanilla lazy on iOS 15.
410 if (!$this->browser_lazy) {
411 add_filter('wp_lazy_loading_enabled', '__return_false');
412
413 if ($TwoSettings->get_settings('two_remove_elementor_lazyload') == 'on') {
414 add_action('elementor/widget/render_content', function ($content, $widget) {
415 if ($widget->get_name() === 'image') {
416 $content = str_replace(' loading="lazy"', '', $content);
417 }
418
419 return $content;
420 }, 10, 2);
421 }
422 }
423
424 if (!isset($_GET['two_optimize_only_images'])) { // phpcs:ignore
425 add_action('wp_head', [ $this, 'add_delayed_javascript_execution_script_header' ], -1000000000, 0);
426 add_action('wp_default_scripts', [ $this, 'dequeue_jquery_migrate' ]);
427
428 if ($two_disable_wp_dashicons == 'on') {
429 add_action('wp_print_styles', [ $this, 'two_deregister_styles' ], 100);
430 }
431
432 if ($this->two_youtube_vimeo_iframe_lazyload == 'on') {
433 add_action('wp_enqueue_scripts', [ $this, 'two_enqueue_styles' ]);
434 }
435
436 if ($this->two_lazyload == 'on' ||
437 $this->two_iframe_lazyload == 'on' ||
438 $this->two_bg_lazyload == 'on' ||
439 $this->two_video_lazyload == 'on' ||
440 $this->two_youtube_vimeo_iframe_lazyload == 'on' ||
441 $this->two_do_not_optimize_images == 'on') {
442 $this->ao_imgopt = new OptimizerImages([
443 'two_iframe_lazyload' => $this->two_iframe_lazyload,
444 'two_youtube_vimeo_iframe_lazyload' => $this->two_youtube_vimeo_iframe_lazyload,
445 ]);
446 $this->ao_imgopt->run();
447 }
448
449 if (!empty($this->is_testing)) {
450 echo wp_kses_post($this->end_buffering($this->is_testing));
451 die;
452 }
453
454 if (isset($post->ID)) {
455 $this->set_modes($post->ID);
456 }
457 add_action('wp_meta', [ $this, 'two_meta' ]);
458 }
459 self::add_optimization_status_headers();
460 ob_start([ $this, 'end_buffering' ], 0, PHP_OUTPUT_HANDLER_REMOVABLE);
461 } elseif (is_string($should_serve_optimized_page)) {
462 OptimizerLogger::add_not_optimized_page_log($should_serve_optimized_page);
463 self::add_optimization_status_headers(0, $should_serve_optimized_page);
464 }
465 global $disableTwoCacheStructureCache;
466
467 if ($disableTwoCacheStructureCache === true) {
468 OptimizerLogger::add_not_optimized_page_log('Page is served optimized but bypassed cache structure caching');
469 }
470
471 if (isset($_GET[ 'two_detect_post_id' ])) { // phpcs:ignore
472 $current_post = OptimizerUtils::get_current_post_info();
473 header('X-TWO-POST-ID: ' . $current_post);
474 }
475 }
476
477 public static function add_optimization_status_headers($status = 1, $code = '')
478 {
479 header('X-TWO-PAGE-IS-OPTIMIZED: ' . $status);
480
481 if ($code) {
482 header('X-TWO-OPTIMIZE-REASON: ' . $code);
483 }
484 }
485
486 public static function two_headers()
487 {
488 global $TwoSettings;
489 header('X-TWO-OPTIMIZE: 1'); // do not edit, this is used in service to determine whether plugin is enabled.
490 header('X-TWO-VERSION: ' . $TwoSettings->get_settings('tenweb_so_version', 'Clear the cache to see the version'));
491 header('X-TWO-CACHE-DATE: ' . $TwoSettings->get_settings('two_clear_cache_date'));
492
493 if ($TwoSettings->get_settings('two_webp_delivery_working') == 1) {
494 header('X-TWO-WEBP: 1');
495 }
496
497 if ($TwoSettings->get_settings('two_test_mode') == 'on') {
498 header('X-TWO-TEST-MODE: 1');
499 }
500
501 if (isset($_GET['two_critical_status'])) { // phpcs:ignore
502 $two_critical_status = $TwoSettings->get_settings('two_critical_status');
503 $two_critical_pages = \TenWebOptimizer\OptimizerUtils::getCriticalPages();
504
505 if ($two_critical_status == 'true' && isset($two_critical_pages) && is_array($two_critical_pages)) {
506 if (isset($two_critical_pages[ 'front_page' ]) && get_option('tenweb_import_in_progress') != 1) {
507 header('X-TWO-CRITICAL: ' . $two_critical_pages[ 'front_page' ][ 'status' ]);
508 } else {
509 header('X-TWO-CRITICAL: not_started');
510 }
511 }
512 }
513 }
514
515 public function two_meta()
516 {
517 global $TwoSettings;
518
519 if ($this->two_webp_delivery_working == 1) {
520 echo '<meta name="X-TWO-WEBP" content="1">';
521 }
522 echo '<meta name="X-TWO-OPTIMIZE" content="1">';
523 echo '<meta name="X-TWO-CACHE-DATE" content="' . esc_attr($TwoSettings->get_settings('two_clear_cache_date')) . '">';
524 }
525
526 public function two_deregister_styles()
527 {
528 wp_deregister_style('dashicons');
529 }
530
531 public function two_enqueue_styles()
532 {
533 wp_enqueue_style('two_yt_vi_css', TENWEB_SO_URL . '/includes/external/css/two_yt_vi_lazyload.min.css', '', TENWEB_SO_VERSION);
534 }
535
536 public function add_delayed_javascript_execution_script_header()
537 {
538 echo trim(JSMin::minify('<script ' . esc_attr(OptimizerScripts::TWO_DISABLE_PAGESPEED_DEFER_ATTRIBUTE) . ' ' . esc_attr(OptimizerScripts::TWO_NO_DELAYED_JS_ATTRIBUTE) . ' type="text/javascript">' . file_get_contents(__DIR__ . '/external/js/loader.js') . '</script>')); // phpcs:ignore
539
540 if ($this->two_delay_all_js_execution) {
541 global $TwoSettings;
542 $two_delay_custom_js_new = $TwoSettings->get_settings('two_delay_custom_js_new');
543
544 if (!empty($two_delay_custom_js_new) && !ctype_space($two_delay_custom_js_new)) {
545 echo '<script ' . esc_attr(OptimizerScripts::TWO_DISABLE_PAGESPEED_DEFER_ATTRIBUTE) . ' ' . esc_attr(OptimizerScripts::TWO_NO_DELAYED_JS_ATTRIBUTE) . ' type="text/javascript">
546 const two_delay_custom_js_new = new Event("two_delay_custom_js_new");
547 document.addEventListener("two_delay_custom_js_new", event => {
548 ' . esc_js(stripslashes($two_delay_custom_js_new)) . '
549 })
550 </script>';
551 }
552
553 echo trim(JSMin::minify('<script ' . esc_attr(OptimizerScripts::TWO_DISABLE_PAGESPEED_DEFER_ATTRIBUTE) . ' ' . esc_attr(OptimizerScripts::TWO_NO_DELAYED_JS_ATTRIBUTE) . ' type="text/javascript">' . // phpcs:ignore
554 'window.two_delayed_loading_attribute = "' . OptimizerScripts::TWO_DELAYED_JS_ATTRIBUTE . '";
555 window.two_delayed_js_load_libs_first = "' . esc_html($this->two_delayed_js_load_libs_first) . '";
556 window.two_delayed_loading_events = ["mousemove", "click", "keydown", "wheel", "touchmove", "touchend"];
557 window.two_event_listeners = [];
558
559 </script>'));
560
561 if ($this->two_timeout_js_load) {
562 echo '<script ' . esc_attr(OptimizerScripts::TWO_DISABLE_PAGESPEED_DEFER_ATTRIBUTE) . ' ' . esc_attr(OptimizerScripts::TWO_NO_DELAYED_JS_ATTRIBUTE) . ' type="text/javascript">
563 setTimeout(function() {
564 two_load_delayed_javascript();
565 },1500);
566 </script>';
567 }
568 } elseif ($this->two_delay_js_execution) {
569 echo '<script ' . esc_attr(OptimizerScripts::TWO_DISABLE_PAGESPEED_DEFER_ATTRIBUTE) . ' ' . esc_attr(OptimizerScripts::TWO_NO_DELAYED_JS_ATTRIBUTE) . ' type="text/javascript">' .
570 'window.two_delayed_loading_attribute = "' . esc_attr(OptimizerScripts::TWO_DELAYED_JS_ATTRIBUTE) . '";
571 window.two_delayed_js_load_libs_first = "' . esc_html($this->two_delayed_js_load_libs_first) . '";
572 window.two_delayed_loading_events = ["mousemove", "click", "keydown", "wheel", "touchmove", "touchend"];
573 window.two_event_listeners = [];
574 var two_load_delayed_javascript = function(event) {
575 var delayedScripts = [].map.call(document.querySelectorAll("script[" + window.two_delayed_loading_attribute + "]"), function(elm){
576 return elm;
577 })
578
579 if (window.two_delayed_js_load_libs_first === "on" ) {
580 delayedScripts = delayedScripts.sort(function (a, b) {
581 isLiba = a.outerHTML.indexOf("data:");
582 isLibb = b.outerHTML.indexOf("data:");
583
584 return isLiba - isLibb;
585 });
586 }
587 delayedScripts.forEach(function(elem) {
588 var src = elem.getAttribute(window.two_delayed_loading_attribute);
589 elem.setAttribute("src", src);
590 elem.removeAttribute(window.two_delayed_loading_attribute);
591 window.two_delayed_loading_events.forEach(function(event) {
592 document.removeEventListener(event, two_load_delayed_javascript, false)
593 });
594 })
595 };' .
596 '</script>';
597 }
598
599 if ($this->critical->uncritical_load_type === 'on_interaction' && $this->critical->critical_enabled) {
600 echo trim(JSMin::minify('<script ' . esc_attr(OptimizerScripts::TWO_DISABLE_PAGESPEED_DEFER_ATTRIBUTE) . ' ' . esc_attr(OptimizerScripts::TWO_NO_DELAYED_JS_ATTRIBUTE) . ' type="text/javascript">' . // phpcs:ignore
601 'window.two_delayed_loading_attribute_css = "' . esc_attr(OptimizerStyles::TWO_DELAYED_CSS_ATTRIBUTE) . '";
602 window.two_delayed_loading_events_css = ["keydown", "mouseover", "touchmove", "touchstart"];
603 window.two_event_listeners_css = [];
604 var two_load_delayed_css = function(event) {
605 var delayedStyle = [].map.call(document.querySelectorAll("link[" + window.two_delayed_loading_attribute_css + "]"), function(elm){
606 return elm;
607 })
608
609 delayedStyle.forEach(function(elem) {
610 var src = elem.getAttribute(window.two_delayed_loading_attribute_css);
611 elem.setAttribute("href", src);
612 elem.removeAttribute(window.two_delayed_loading_attribute_css);
613 window.two_delayed_loading_events_css.forEach(function(event) {
614 document.removeEventListener(event, two_load_delayed_css, false)
615 });
616 })
617 };' .
618 '</script>'));
619 }
620
621 if ($this->two_delay_iframe_lazyload == 'on') {
622 echo '<script ' . esc_attr(OptimizerScripts::TWO_DISABLE_PAGESPEED_DEFER_ATTRIBUTE) . ' ' . esc_attr(OptimizerScripts::TWO_NO_DELAYED_JS_ATTRIBUTE) . ' type="text/javascript">' .
623 'window.two_delayed_iframe_loading_attribute = "' . esc_attr('data-src') . '";
624 window.two_delayed_loading_iframe_events = ["keydown", "mouseover", "touchmove", "touchstart"];
625 window.two_iframe_event_listeners = [];
626 var two_load_delayed_iframe = function(event) {
627 var delayedIframes = [].map.call(document.querySelectorAll("iframe.lazy_delay"), function(elm){
628 return elm;
629 })
630
631 delayedIframes.forEach(function(elem) {
632 var src = elem.getAttribute(window.two_delayed_iframe_loading_attribute);
633 elem.setAttribute("src", src);
634 elem.removeAttribute(window.two_delayed_iframe_loading_attribute);
635 window.two_delayed_loading_iframe_events.forEach(function(event) {
636 document.removeEventListener(event, two_load_delayed_iframe, false)
637 });
638 })
639 };' .
640 '</script>';
641 }
642 echo trim(JSMin::minify('<script ' . esc_attr(OptimizerScripts::TWO_DISABLE_PAGESPEED_DEFER_ATTRIBUTE) . ' ' . esc_attr(OptimizerScripts::TWO_NO_DELAYED_JS_ATTRIBUTE) . // phpcs:ignore
643 ' type="text/javascript">
644 // Register delayed scripts load on document load event
645 document.onreadystatechange = function () {
646 if (document.readyState === "interactive") {
647 if(window.two_delayed_loading_attribute !== undefined){
648 window.two_delayed_loading_events.forEach(function(ev) { window.two_event_listeners[ev] = document.addEventListener(ev, two_load_delayed_javascript, {passive: false}) });
649 }
650 if(window.two_delayed_loading_attribute_css !== undefined){
651 window.two_delayed_loading_events_css.forEach(function(ev) { window.two_event_listeners_css[ev] = document.addEventListener(ev, two_load_delayed_css, {passive: false}) });
652 }
653 if(window.two_load_delayed_iframe !== undefined){
654 window.two_delayed_loading_iframe_events.forEach(function(ev) { window.two_iframe_event_listeners[ev] = document.addEventListener(ev, two_load_delayed_iframe, {passive: false}) });
655 }
656 }
657 }
658 </script>'));
659 }
660
661 public function add_two_js_footer($content)
662 {
663 $replaceTag = [ '</body>', 'before' ];
664
665 if ($this->TwoSettings->get_settings('two_add_overflow_to_page') != 'off') {
666 // Not using tag_escape as it removes comma from 'body, html'
667 $css = '<style id="two_fix_scroll_issues_style" >' . wp_strip_all_tags($this->TwoSettings->get_settings('two_add_overflow_to_page')) . ' {overflow-y: visible !important;}</style>';
668 $content = OptimizerUtils::inject_in_html($content, $css, $replaceTag);
669 }
670
671 if (is_plugin_active('elementor/elementor.php') && $this->two_delay_all_js_execution && !ExcludeJsFromDelay::plugin_is_excluded('elementor/elementor.php')) {
672 $init_elementor_animations_js = '<script ' . esc_attr(OptimizerScripts::TWO_DISABLE_PAGESPEED_DEFER_ATTRIBUTE) . ' ' . esc_attr(OptimizerScripts::TWO_NO_DELAYED_JS_ATTRIBUTE) . ' >
673 ( function () {
674 window.addEventListener( "two_css_loaded", function () {
675 window.two_observer = new IntersectionObserver( items => {
676 items.forEach( item => {
677 if (item.isIntersecting) {
678 if (item.target.dataset.settings) {
679 let settings = JSON.parse(item.target.dataset.settings);
680 let animation = settings.animation ? settings.animation : settings._animation ? settings._animation : "zoomIn";
681 let delay = settings.animation_delay ? settings.animation_delay : settings._animation_delay ? settings._animation_delay : 0;
682 setTimeout(() => {
683 item.target.className = item.target.className.replace("elementor-invisible", "") + " animated " + animation;
684 }, delay);
685 delete settings.animation;
686 delete settings._animation;
687 item.target.dataset.settings = JSON.stringify(settings);
688 } else {
689 item.target.className = item.target.className.replace("elementor-invisible", "") + " animated zoomIn";
690 }
691 }
692 } )
693 }, {} );
694 document.querySelectorAll( ".elementor-invisible" ).forEach( e => {
695 window.two_observer.observe( e )
696 } )
697 } )
698 } )();
699 </script>';
700 $content = OptimizerUtils::inject_in_html($content, $init_elementor_animations_js, $replaceTag);
701 }
702
703 if (TWO_LAZYLOAD) {
704 if ($this->two_bg_lazyload == 'on' || $this->two_lazyload == 'on' || $this->two_iframe_lazyload == 'on' || $this->two_video_lazyload == 'on' || $this->two_youtube_vimeo_iframe_lazyload == 'on') {
705 if ($this->two_bg_lazyload == 'on') {
706 $bg_placeholder = '<script ' . esc_attr(OptimizerScripts::TWO_DISABLE_PAGESPEED_DEFER_ATTRIBUTE) . ' ' . esc_attr(OptimizerScripts::TWO_NO_DELAYED_JS_ATTRIBUTE) . ' >window["two_svg_placeholder"] = "' . OptimizerUtils::BG_SVG_PLACEHOLDER . '"</script>';
707 $content = OptimizerUtils::inject_in_html($content, $bg_placeholder, $replaceTag);
708 }
709
710 $noptimize_flag = ' data-noptimize="1"';
711
712 if ($this->two_iframe_lazyload == 'on' && $this->two_elemrntor_video_iframe == 'on') {
713 $two_elementor_video_to_iframe_js = '<script ' . esc_attr(OptimizerScripts::TWO_DISABLE_PAGESPEED_DEFER_ATTRIBUTE) . ' ' . esc_attr(OptimizerScripts::TWO_NO_DELAYED_JS_ATTRIBUTE) . ' src="' . plugins_url('external/js/two_elementor_video_to_iframe.js', __FILE__) . '"></script>';
714 $content = OptimizerUtils::inject_in_html($content, $two_elementor_video_to_iframe_js, $replaceTag);
715 }
716
717 if ($this->vanilla_lazy) {
718 $lazyload_min_js = '<script ' . esc_attr(OptimizerScripts::TWO_DISABLE_PAGESPEED_DEFER_ATTRIBUTE) . ' ' . esc_attr(OptimizerScripts::TWO_NO_DELAYED_JS_ATTRIBUTE) . ' type="text/javascript" src="' . plugins_url('external/js/vanilla-lazyload/lazyload.min.js', __FILE__) . '"></script>';
719 $content = OptimizerUtils::inject_in_html($content, $lazyload_min_js, $replaceTag);
720
721 if ($this->two_bg_lazyload == 'on') {
722 $two_bg_vanilla_js = '<script ' . esc_attr(OptimizerScripts::TWO_DISABLE_PAGESPEED_DEFER_ATTRIBUTE) . ' ' . esc_attr(OptimizerScripts::TWO_NO_DELAYED_JS_ATTRIBUTE) . ' type="text/javascript" src="' . plugins_url('external/js/vanilla-lazyload/two_bg_vanilla.js', __FILE__) . '"></script>';
723 $content = OptimizerUtils::inject_in_html($content, $two_bg_vanilla_js, $replaceTag);
724 }
725
726 if ($this->two_youtube_vimeo_iframe_lazyload == 'on') {
727 $two_yt_vi_lazyload_min_js = '<script ' . esc_attr(OptimizerScripts::TWO_DISABLE_PAGESPEED_DEFER_ATTRIBUTE) . ' ' . esc_attr(OptimizerScripts::TWO_NO_DELAYED_JS_ATTRIBUTE) . ' type="text/javascript" data-pagespeed-no-defer ' . OptimizerScripts::TWO_NO_DELAYED_JS_ATTRIBUTE . ' src="' . plugins_url('external/js/two_yt_vi_lazyload.min.js', __FILE__) . '"></script>';
728 $content = OptimizerUtils::inject_in_html($content, $two_yt_vi_lazyload_min_js, $replaceTag);
729 }
730 $init_vanilla_lazy_js = '<script ' . esc_attr(OptimizerScripts::TWO_DISABLE_PAGESPEED_DEFER_ATTRIBUTE) . ' ' . esc_attr(OptimizerScripts::TWO_NO_DELAYED_JS_ATTRIBUTE) . ' >
731 if(typeof two_lazyLoadInstance === "undefined"){
732 window.two_lazyLoadInstance = new LazyLoad({
733 "callback_applied": function(element, instance){
734 let settings = instance._settings;
735 var bgDataValue = element.getAttribute("data-" + settings.data_bg_multi);
736 if (!bgDataValue) {
737 return;
738 }
739 if(window.getComputedStyle(element).getPropertyValue("background-image") !== bgDataValue) {
740 let style = element.getAttribute("style");
741 style += "background-image: " + bgDataValue + " !important;";
742 element.setAttribute("style", style);
743 }
744 }
745 });
746 }else{
747 two_lazyLoadInstance.update();
748 }
749 window.addEventListener("scroll", function() {
750 if(two_lazyLoadInstance.toLoadCount>0){
751 two_lazyLoadInstance.update();
752 }
753 });
754 /*
755 * Updates lazy-load instance from every ajax request
756 * When we use Ajax requests and get pictures back, we need to update lazy-load instance
757 * */
758 if (window.jQuery) {
759 jQuery.ajaxSetup({
760 complete: function() {
761 two_lazyLoadInstance.update();
762 }
763 });
764 }
765 </script>';
766 $content = OptimizerUtils::inject_in_html($content, $init_vanilla_lazy_js, $replaceTag);
767
768 return $content;
769 }
770
771 if (($this->browser_lazy && $this->two_bg_lazyload == 'on') || $this->browser_lazy == false) {
772 $lazySizesConfig_js = '<script ' . esc_attr(OptimizerScripts::TWO_DISABLE_PAGESPEED_DEFER_ATTRIBUTE) . ' ' . esc_attr(OptimizerScripts::TWO_NO_DELAYED_JS_ATTRIBUTE) . ' ' . esc_attr($noptimize_flag) . '>window.lazySizesConfig=window.lazySizesConfig||{};window.lazySizesConfig.loadMode=1;</script>';
773 $content = OptimizerUtils::inject_in_html($content, $lazySizesConfig_js, $replaceTag);
774 $jquery_lazy_min_js = '<script ' . esc_attr(OptimizerScripts::TWO_DISABLE_PAGESPEED_DEFER_ATTRIBUTE) . ' ' . esc_attr(OptimizerScripts::TWO_NO_DELAYED_JS_ATTRIBUTE) . ' src="' . plugins_url('external/js/jquery.lazy.min.js', __FILE__) . '"></script>';
775 $content = OptimizerUtils::inject_in_html($content, $jquery_lazy_min_js, $replaceTag);
776
777 if ($this->two_bg_lazyload == 'on') {
778 $two_lazyload_js = '<script ' . esc_attr(OptimizerScripts::TWO_DISABLE_PAGESPEED_DEFER_ATTRIBUTE) . ' ' . esc_attr(OptimizerScripts::TWO_NO_DELAYED_JS_ATTRIBUTE) . ' src="' . plugins_url('external/js/two_lazyload.js', __FILE__) . '"></script>';
779 $content = OptimizerUtils::inject_in_html($content, $two_lazyload_js, $replaceTag);
780 }
781 }
782
783 if ($this->browser_lazy == false) {
784 if ($this->two_iframe_lazyload == 'on') {
785 $jquery_lazy_iframe_min_js = '<script ' . esc_attr(OptimizerScripts::TWO_DISABLE_PAGESPEED_DEFER_ATTRIBUTE) . ' ' . esc_attr(OptimizerScripts::TWO_NO_DELAYED_JS_ATTRIBUTE) . ' src="' . plugins_url('external/js/jquery.lazy.iframe.min.js', __FILE__) . '"></script>';
786 $content = OptimizerUtils::inject_in_html($content, $jquery_lazy_iframe_min_js, $replaceTag);
787 }
788
789 if ($this->two_video_lazyload == 'on') {
790 $jquery_lazy_av_min_js = '<script ' . esc_attr(OptimizerScripts::TWO_DISABLE_PAGESPEED_DEFER_ATTRIBUTE) . ' ' . esc_attr(OptimizerScripts::TWO_NO_DELAYED_JS_ATTRIBUTE) . ' src="' . plugins_url('external/js/jquery.lazy.av.min.js', __FILE__) . '"></script>';
791 $content = OptimizerUtils::inject_in_html($content, $jquery_lazy_av_min_js, $replaceTag);
792 }
793
794 if ($this->two_youtube_vimeo_iframe_lazyload == 'on') {
795 $two_yt_vi_lazyload_min_js = '<script ' . esc_attr(OptimizerScripts::TWO_DISABLE_PAGESPEED_DEFER_ATTRIBUTE) . ' ' . esc_attr(OptimizerScripts::TWO_NO_DELAYED_JS_ATTRIBUTE) . ' src="' . plugins_url('external/js/two_yt_vi_lazyload.min.js', __FILE__) . '"></script>';
796 $content = OptimizerUtils::inject_in_html($content, $two_yt_vi_lazyload_min_js, $replaceTag);
797 }
798 }
799
800 if (($this->browser_lazy && $this->two_bg_lazyload == 'on') || $this->browser_lazy == false) {
801 $lazy_script = '<script ' . esc_attr(OptimizerScripts::TWO_DISABLE_PAGESPEED_DEFER_ATTRIBUTE) . ' ' . esc_attr(OptimizerScripts::TWO_NO_DELAYED_JS_ATTRIBUTE) . " >
802 window.onload = function() {
803 jQuery('.lazyload').Lazy({
804 visibleOnly:true,
805 afterLoad: function(element) {
806 element.css('display', '');
807 }
808 });
809 }
810 </script>";
811 $content = OptimizerUtils::inject_in_html($content, $lazy_script, $replaceTag);
812 }
813 }
814 }
815
816 return $content;
817 }
818
819 public function dequeue_jquery_migrate($scripts)
820 {
821 if ($this->two_dequeue_jquery_migrate == 'on' && !is_admin() && !empty($scripts->registered['jquery']) && !empty($scripts->registered['jquery']->deps)) {
822 $scripts->registered['jquery']->deps = array_diff(
823 $scripts->registered['jquery']->deps,
824 ['jquery-migrate']
825 );
826 }
827 }
828
829 /**
830 * Returns optimized HTML content
831 *
832 * @return mixed|string|void
833 *
834 * @throws InvalidSelectorException
835 */
836 private function end_buffering($content)
837 {
838 $content = apply_filters('two_content_before_optimization', $content, 10, 1);
839
840 $is_content_optimizable = OptimizerUrl::isUrlOptimizableByContent($content);
841
842 if (true !== $is_content_optimizable) {
843 self::add_optimization_status_headers(0, $is_content_optimizable);
844
845 return $content;
846 }
847
848 /**
849 * optimize options
850 */
851 $classoptions = [
852 'OptimizerScripts' => [
853 'aggregate' => $this->aggregate_js,
854 'forcehead' => '',
855 'trycatch' => '',
856 'delay_js_execution' => $this->two_delay_js_execution,
857 'delay_all_js_execution' => $this->two_delay_all_js_execution,
858 'use_extended_exception_list_js' => $this->use_extended_exception_list_js,
859 'delayed_js_execution_list' => $this->two_delayed_js_execution_list,
860 'js_exclude' => $this->two_exclude_js,
861 'exclude_delay_js' => $this->two_exclude_delay_js,
862 'disabled_delay_all_js_pages' => $this->two_disabled_delay_all_js_pages,
863 'load_excluded_js_normally' => $this->two_load_excluded_js_normally,
864 'cdn_url' => '',
865 'include_inline' => $this->two_include_inline_js,
866 'minify_excluded' => $this->minify_js,
867 'two_delay_js_exclusions' => $this->two_delay_js_exclusions,
868 ],
869 'OptimizerStyles' => [
870 'aggregate' => $this->aggregate_css,
871 'defer' => '',
872 'defer_inline' => '',
873 'inline' => '',
874 'css_exclude' => $this->two_exclude_css,
875 'include_inline' => $this->two_include_inline_css,
876 'nogooglefont' => false,
877 'minify_css' => $this->minify_css,
878 'async_all' => $this->async_all,
879 'disable_async' => false
880 ],
881 ];
882
883 if (isset($_GET['two_optimize_only_images']) && $_GET['two_optimize_only_images'] === '1') { // phpcs:ignore
884 if (!empty($content) && (function_exists('wp_filter_content_tags') || function_exists('wp_make_content_images_responsive'))) {
885 $content = OptimizerImages::add_attachment_id_to_img($content);
886 }
887 $content = OptimizerUtils::injectCriticalBg($content, $this->critical, $this->cacheStructure);
888
889 return $content;
890 }
891
892 if ($this->cacheStructure->check($content)) {
893 $content = $this->cacheStructure->retrieve($content);
894 } elseif ($this->cacheStructure->getCacheStatus()) {
895 $this->cacheStructure->setCacheHeaderString('MISS');
896 }
897
898 // Moved HTML minification before js injection as it breaks scripts containing =>
899 // Can be moved to the end if library fixes the issue
900 if ($this->two_minify_html) {
901 $content = \Minifier\TinyMinify::html($content);
902 }
903
904 if (!$this->cacheStructure->isFromCache()) {
905 /*
906 * optimize css
907 * */
908 $twoptimizeStyles = new OptimizerStyles($content, $this->cacheStructure, $this->critical);
909
910 if (isset($this->critical) && isset($this->critical->critical_css) && $this->critical->critical_enabled && $this->critical->status == 'success') {
911 if ($this->critical->uncritical_load_type !== 'not_load') {
912 if ($this->critical->uncritical_load_type === 'async') {
913 $classoptions['OptimizerStyles']['async_all'] = true;
914 } elseif ($this->critical->uncritical_load_type === 'on_interaction') {
915 $classoptions['OptimizerStyles']['include_inline'] = true;
916 $classoptions['OptimizerStyles']['disable_async'] = true;
917 }
918 $twoptimizeStyles->read($classoptions['OptimizerStyles']);
919 $twoptimizeStyles->optimize();
920 $twoptimizeStyles->cache();
921 }
922 } else {
923 $twoptimizeStyles->read($classoptions['OptimizerStyles']);
924 $twoptimizeStyles->optimize();
925 $twoptimizeStyles->cache();
926 }
927 $content = $twoptimizeStyles->getcontent();
928
929 /*
930 * optimize js
931 * */
932 $twoptimizeScripts = new OptimizerScripts($content, $this->cacheStructure);
933 $twoptimizeScripts->read($classoptions['OptimizerScripts']);
934 $twoptimizeScripts->optimize();
935 $twoptimizeScripts->cache();
936 $content = $twoptimizeScripts->getcontent();
937
938 if (!empty($twoptimizeStyles->two_async_css_arr) || !empty($twoptimizeScripts->two_js_list) || !empty($this->critical_fonts_arr) || !empty($twoptimizeScripts->two_js_list_excluded)) {
939 $two_worker_data_to_inject_css = $this->get_two_worker_data_script_tag(
940 [
941 'css' => $twoptimizeStyles->two_async_css_arr,
942 ],
943 '_css'
944 );
945 $two_worker_data_to_inject_js = $this->get_two_worker_data_script_tag(
946 [
947 'js' => $twoptimizeScripts->two_js_list
948 ],
949 '_js'
950 );
951 $two_worker_data_to_inject_excluded_js = $this->get_two_worker_data_script_tag(
952 [
953 'js' => $twoptimizeScripts->two_js_list_excluded
954 ],
955 '_excluded_js'
956 );
957
958 $two_worker_data_to_inject_font = $this->get_two_worker_data_script_tag(
959 [
960 'font' => $twoptimizeStyles->critical_fonts_arr,
961 ],
962 '_font'
963 );
964 $two_worker_data_to_inject_critical_status = $this->get_two_worker_data_script_tag(
965 [
966 'critical_data' => $twoptimizeStyles->two_critical_connection_data,
967 ],
968 '_critical_data'
969 );
970 $two_worker_script = OptimizerUtils::get_worker_script();
971
972 if (!empty($twoptimizeStyles->two_async_css_arr)) {
973 foreach ($twoptimizeStyles->two_async_css_arr as $async_css) {
974 if (!empty($async_css) && isset($async_css['media'], $async_css['url'])) {
975 $two_worker_data_to_inject_css .= '<noscript><link rel="stylesheet" crossorigin="anonymous" class="two_uncritical_css_noscript" media="' . $async_css['media'] . '" href="' . stripslashes($async_css['url']) . '"></noscript>';
976 }
977 }
978 }
979
980 $content = OptimizerUtils::inject_in_html($content, $two_worker_data_to_inject_css, ['<head', 'after_tag']);
981 $content = OptimizerUtils::inject_in_html($content, $two_worker_data_to_inject_js, ['<head', 'after_tag']);
982 $content = OptimizerUtils::inject_in_html($content, $two_worker_data_to_inject_excluded_js, ['<head', 'after_tag']);
983 $content = OptimizerUtils::inject_in_html($content, $two_worker_data_to_inject_font, ['<head', 'after_tag']);
984 $content = OptimizerUtils::inject_in_html($content, $two_worker_data_to_inject_critical_status, ['<head', 'after_tag']);
985 $content = OptimizerUtils::inject_in_html($content, $two_worker_script, ['<body', 'after_tag']);
986
987 $this->cacheStructure->addToTagsToAdd($two_worker_data_to_inject_css, ['<head', 'after_tag']);
988 $this->cacheStructure->addToTagsToAdd($two_worker_data_to_inject_js, ['<head', 'after_tag']);
989 $this->cacheStructure->addToTagsToAdd($two_worker_data_to_inject_excluded_js, ['<head', 'after_tag']);
990 $this->cacheStructure->addToTagsToAdd($two_worker_data_to_inject_font, ['<head', 'after_tag']);
991 $this->cacheStructure->addToTagsToAdd($two_worker_data_to_inject_critical_status, ['<head', 'after_tag']);
992 $this->cacheStructure->addToTagsToAdd($two_worker_script, ['<body', 'after_tag']);
993 }
994
995 //sets cache
996 $this->cacheStructure->set();
997 }
998
999 if ($this->cacheStructure->isFromCache()) {
1000 $webFontList = $this->cacheStructure->getWebFontList();
1001 } else {
1002 $this->cacheStructure->addToWebFontList($twoptimizeStyles->webFont_list);
1003 $webFontList = $twoptimizeStyles->webFont_list;
1004 }
1005
1006 /*
1007 * optimize fonts
1008 */
1009 if (!empty($webFontList) && is_array($webFontList)) {
1010 $fontOptimize_options = [
1011 'webFont_list' => $webFontList
1012 ];
1013 $fontOptimize = new OptimizerFonts($content);
1014 $fontOptimize->read($fontOptimize_options);
1015 $fontOptimize->optimize();
1016 $content = $fontOptimize->getcontent();
1017
1018 $this->cacheStructure->addCacheHeaders();
1019 }
1020
1021 // This code is moved after the script optimization
1022 // Otherwise img tags inside ElementorFrontend config are breaking the js
1023 // They may be in ElementorFrontendConfig.post.excerpt and WP is trying to add decoding="async" to them without adding slashes
1024 // Not a perfect solution as the issue wil arise if js aggregation is off.
1025 if ($this->two_enable_use_srcset === 'on') {
1026 // Skip parsing the html if WP version does not support responsive images.
1027 if (!empty($content) && (function_exists('wp_filter_content_tags') || function_exists('wp_make_content_images_responsive'))) {
1028 $content = OptimizerImages::add_attachment_id_to_img($content);
1029 }
1030 }
1031
1032 // Do not replace images with picture if delivery by hosting is enabled.
1033 if ($this->two_enable_picture_webp_delivery === 'on' && !TENWEB_SO_HOSTED_ON_10WEB && !$this->two_webp_delivery_working) {
1034 $content = OptimizerImages::replace_img_with_picture($content);
1035 }
1036
1037 if ($this->two_bg_lazyload === 'on') {
1038 $content = OptimizerUtils::replace_bg($content);
1039 }
1040
1041 if ($this->two_lazyload == 'on') {
1042 $content = apply_filters('twoptimize_html_after_minify', $content);
1043 }
1044
1045 if ($this->two_video_lazyload == 'on') {
1046 $content = apply_filters('twoptimize_html_after_minify_video', $content);
1047 }
1048
1049 if ($this->two_iframe_lazyload == 'on' || $this->two_youtube_vimeo_iframe_lazyload == 'on') {
1050 $content = apply_filters('twoptimize_html_after_minify_iframe', $content);
1051 }
1052 $content = apply_filters('twoptimize_html_images', $content);
1053
1054 $this->reinit_lazy_load_options();
1055 $content = $this->add_two_js_footer($content);
1056
1057 $content = apply_filters('two_content_after_optimization', $content, 10, 1);
1058
1059 return $content;
1060 }
1061
1062 private function get_two_worker_data_script_tag($data, $suffix = '')
1063 {
1064 return '<script ' . esc_attr(OptimizerScripts::TWO_DISABLE_PAGESPEED_DEFER_ATTRIBUTE) . ' ' . esc_attr(OptimizerScripts::TWO_NO_DELAYED_JS_ATTRIBUTE) . ' ' .
1065 'type="text/javascript" >var two_worker_data' . $suffix . ' = ' . json_encode($data) . '</script>'; // phpcs:ignore
1066 }
1067
1068 private function check_cache_dir($dir)
1069 {
1070 // Try creating the dir if it doesn't exist.
1071 if (!file_exists($dir)) {
1072 if (!mkdir($dir, 0777, true) && !is_dir($dir)) { // phpcs:ignore
1073 return false;
1074 }
1075
1076 if (!file_exists($dir)) {
1077 return false;
1078 }
1079 }
1080
1081 // If we still cannot write, bail.
1082 if (!is_writable($dir)) { // phpcs:ignore
1083 return false;
1084 }
1085 // Create an index.html in there to avoid prying eyes!
1086 $idx_file = rtrim($dir, '/\\') . '/index.html';
1087
1088 if (!is_file($idx_file)) {
1089 @file_put_contents($idx_file, '<html><head><meta name="robots" content="noindex, nofollow"></head><body></body></html>'); // phpcs:ignore
1090 }
1091
1092 return true;
1093 }
1094
1095 private function check_and_create_dirs()
1096 {
1097 if (!defined('TENWEB_SO_CACHE_CHILD_DIR')) {
1098 // We didn't set a cache.
1099 return false;
1100 }
1101
1102 foreach (['', 'js', 'css'] as $dir) {
1103 if (!$this->check_cache_dir(OptimizerCache::get_path() . $dir)) {
1104 return false;
1105 }
1106 }
1107
1108 return true;
1109 }
1110
1111 private function clear_cache()
1112 {
1113 $dir = OptimizerCache::get_path();
1114 $delete_cache_db = OptimizerUtils::delete_all_cache_db();
1115 $delete_cache_file = OptimizerUtils::delete_all_cache_file($dir, [$dir, $dir . '/css', $dir . '/js']);
1116 OptimizerUtils::flushCloudflareCache();
1117 do_action('tenweb_purge_all_caches');
1118
1119 return $delete_cache_file && $delete_cache_db;
1120 }
1121
1122 private function set_modes($post_id)
1123 {
1124 $post_mode = get_post_meta($post_id, 'two_mode', true);
1125
1126 if ((isset($_GET['two_mode']) && !empty($_GET['two_mode'])) || (isset($_GET['two_level']) && !empty($_GET['two_level']))) { // phpcs:ignore
1127 if (isset($_GET['two_mode'])) { // phpcs:ignore
1128 $mode_name = sanitize_text_field($_GET['two_mode']); // phpcs:ignore
1129 $mode = OptimizerUtils::get_modes($mode_name);
1130 } elseif (isset($_GET['two_level'])) { // phpcs:ignore
1131 $level = (int) $_GET['two_level']; // phpcs:ignore
1132 $mode = OptimizerUtils::get_modes(null, false, $level);
1133 }
1134 } else {
1135 $mode = $post_mode;
1136 }
1137
1138 if (is_array($mode) && isset($mode['mode'])) {
1139 foreach ($mode as $key => $val) {
1140 $val = ($val === '1' || $val === true);
1141
1142 if ($key == 'critical_enabled') {
1143 $this->critical->critical_enabled = $val;
1144 } elseif (isset($this->$key)) {
1145 $this->$key = $val;
1146 }
1147 }
1148 }
1149 }
1150
1151 private function reinit_lazy_load_options()
1152 {
1153 if (!$this->ao_imgopt) {
1154 return;
1155 }
1156
1157 $smart_ll_data = $this->ao_imgopt->get_smart_lazy_load_data();
1158
1159 if ($this->two_youtube_vimeo_iframe_lazyload === 'on' && !isset($smart_ll_data['two_youtube_vimeo_iframe_lazyload'])) {
1160 $this->two_youtube_vimeo_iframe_lazyload = 'off';
1161 }
1162
1163 if ($this->two_iframe_lazyload === 'on' && !isset($smart_ll_data['iframe'])) {
1164 $this->two_iframe_lazyload = 'off';
1165 }
1166
1167 if ($this->two_bg_lazyload === 'on' && OptimizerUtils::has_changed_bg_image() === false) {
1168 $this->two_bg_lazyload = 'off';
1169 }
1170
1171 if ($this->two_elemrntor_video_iframe === 'on' && $this->elementor_youtube_video === false) {
1172 $this->two_elemrntor_video_iframe = 'off';
1173 }
1174 }
1175
1176 public function detect_elementor_video_widget($widget_content, $widget)
1177 {
1178 if ($widget->get_name() === 'video') {
1179 $active_settings = $widget->get_active_settings();
1180
1181 if (isset($active_settings['video_type']) && $active_settings['video_type'] === 'youtube' && !empty($active_settings['youtube_url'])) {
1182 $this->elementor_youtube_video = true;
1183 }
1184 }
1185
1186 return $widget_content;
1187 }
1188
1189 private function should_serve_optimized_page($post_mode)
1190 {
1191 /*
1192 * Function decides whether optimized page should be served or no. It returns boolean or sting. If returns sting
1193 * it contains the reason why page should not be optimized
1194 * @returns bool | string
1195 * */
1196
1197 if (is_admin() || is_user_logged_in()) {
1198 return false;
1199 }
1200
1201 if (is_search()) {
1202 return 'Search page';
1203 }
1204
1205 if (isset($_GET['two_critical_status']) || isset($_GET['two_action']) || isset($_GET['two_nooptimize']) || isset($_GET['elementor-preview'])) { // phpcs:ignore
1206 return false;
1207 }
1208
1209 // don't optimize rest requests
1210 if (\TenWebOptimizer\OptimizerUtils::is_rest()) {
1211 return 'Rest request';
1212 }
1213
1214 // only run on GET requests
1215 if (!\TenWebOptimizer\OptimizerCache::isGetRequest()) {
1216 $method = (isset($_SERVER['REQUEST_METHOD'])) ? sanitize_text_field($_SERVER['REQUEST_METHOD']) : 'unknown';
1217
1218 return 'Request mode is: ' . $method;
1219 }
1220
1221 if (isset($_GET['two_mode']) && $_GET['two_mode'] === 'no_optimize') { // phpcs:ignore
1222 return 'two_mode GET parameter is no_optimize';
1223 }
1224
1225 if ($post_mode == 'no_optimize') {
1226 return 'post mode is ' . $post_mode;
1227 }
1228
1229 if ($this->two_test_mode === 'on' && !isset($_GET['twbooster'])) { // phpcs:ignore
1230 return 'test mode is enabled';
1231 }
1232
1233 // Check for error status codes
1234 $http_response_code = http_response_code();
1235
1236 if ($http_response_code && in_array($http_response_code, TWO_NOT_OPTIMIZED_STATUS_LIST)) {
1237 return 'HTTP status code is: ' . $http_response_code;
1238 }
1239
1240 return \TenWebOptimizer\OptimizerUrl::urlIsOptimizableWithReason();
1241 }
1242 }
1243