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