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 / OptimizerSettings.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
OptimizerSettings.php
1563 lines
1 <?php
2
3 namespace TenWebOptimizer;
4
5 use Exception;
6 use JsonException;
7 use TenwebServices;
8
9 class OptimizerSettings
10 {
11 protected static $instance = null;
12
13 private $two_settings = [];
14 /*
15 * general
16 * css
17 * js
18 * lazyload
19 * images
20 * critical_css
21 * css_in_specific_page
22 * */
23
24 public $settings_names = [
25 /*Start general */
26 'two_gzip' => [
27 'type' => 'checkbox',
28 'default' => '',
29 'tab' => 'general',
30 'title' => '',
31 'description' => '',
32 'accepted_value' => ['on', 'off'],
33 ],
34 'two_page_cache' => [
35 'type' => 'checkbox',
36 'default' => '',
37 'tab' => 'general',
38 'title' => 'Enable page cache',
39 'description' => 'Enable this option to reuse generated static html files for every request and speed up page loading speed.',
40 'accepted_value' => ['on', 'off'],
41 ],
42 'two_page_cache_user' => [
43 'type' => 'checkbox',
44 'default' => '',
45 'tab' => 'general',
46 'title' => 'Enable page cache for logged in users',
47 'description' => 'Enable this option to reuse generated static html files for every request and speed up page loading speed. Page cache lifetime will be 2 days and size limit 3Gb',
48 'accepted_value' => ['on', 'off'],
49 ],
50 'two_serve_gzip' => [
51 'type' => 'checkbox',
52 'default' => 'on',
53 'tab' => 'general',
54 'title' => 'Serve compressed HTML',
55 'description' => '',
56 'accepted_value' => ['on', 'off'],
57 ],
58 'two_empty_encoding_serve_gzip' => [
59 'type' => 'checkbox',
60 'default' => '',
61 'tab' => 'general',
62 'title' => 'Serve compressed HTML in any case',
63 'description' => 'Serve compressed HTML when no "Accept-Encoding" header is provided',
64 'accepted_value' => ['on', 'off'],
65 ],
66 'two_minify_html' => [
67 'type' => 'checkbox',
68 'default' => '',
69 'tab' => 'general',
70 'title' => 'Minify HTML',
71 'description' => 'Enable this option to serve minified HTML.',
72 'accepted_value' => ['on', 'off'],
73 ],
74 'two_page_cache_life_time' => [
75 'type' => 'string',
76 'default' => '',
77 'tab' => 'general',
78 'title' => 'Page cache life time',
79 'description' => 'Page cache life time in seconds. The default value is 7 days.',
80 'accepted_value' => 'string',
81 ],
82 'two_disable_jetpack_optimization' => [
83 'type' => 'checkbox',
84 'default' => '',
85 'tab' => 'general',
86 'title' => 'Disable Jetpack optimization',
87 'description' => 'This option will disable Performance & speed options of Jetpack plugin.',
88 'do_not_render' => true,
89 'accepted_value' => ['on', 'off'],
90 ],
91 'two_generate_ccss_on_load' => [
92 'type' => 'multiselect',
93 'default' => '',
94 'tab' => 'general',
95 'title' => 'Generate CCSS on load',
96 'values' => ['Pages' => 'page', 'Posts' => 'post', 'Taxonomies' => 'taxonomy'],
97 'description' => 'Post Types where CCSS will be generated on first load in incognito.',
98 'accepted_value' => 'array',
99 ],
100 'two_fonts_to_preload' => [
101 'type' => 'textarea',
102 'default' => '',
103 'tab' => 'general',
104 'title' => 'Links that Need to be Preloaded',
105 'description' => 'List of links that you can preload to increase site speed',
106 'accepted_value' => 'string',
107 ],
108 'two_fonts_to_preconnect' => [
109 'type' => 'textarea',
110 'default' => false,
111 'tab' => 'general',
112 'title' => 'Links that Need to be Preconnected',
113 'description' => 'List of links that you can preconnect to increase site speed',
114 'accepted_value' => 'string',
115 ],
116 'two_disabled_speed_optimizer_pages' => [
117 'type' => 'textarea',
118 'default' => '',
119 'tab' => 'general',
120 'title' => 'Pages Where 10Web Booster is Disabled',
121 'description' => 'Paths of web pages where 10Web Booster will not work. For making all pages optimizable set two_all_pages_are_optimizable option to true.<br>
122 "^/[^.]+$" use this expression to exclude all pages except the homepage (w/o quotes)<br>
123 "^/$" use this expression to exclude homepage (w/o quotes)<br>
124 "^((?!red|green|blue).)*$" use this expression to exclude every string that not contains red, green or blue words (w/o quotes)<br>
125 add any subdirectory before the slash in expression (e.g. /wordpress/) if the site is in subdirectory.',
126 'accepted_value' => 'string',
127 ],
128 'two_async_font' => [
129 'type' => 'checkbox',
130 'default' => '',
131 'tab' => 'general',
132 'title' => 'Font Swap',
133 'description' => 'Displays data with generic font while your font style is being fetched.',
134 'accepted_value' => ['on', 'off'],
135 ],
136 'two_merge_google_font_faces' => [
137 'type' => 'checkbox',
138 'default' => 'general',
139 'tab' => '',
140 'title' => 'Merge google font faces',
141 'description' => 'Merge Google font faces before connecting',
142 'accepted_value' => ['on', 'off'],
143 ],
144 'two_load_fonts_via_webfont' => [
145 'type' => 'checkbox',
146 'default' => '',
147 'tab' => 'general',
148 'title' => 'Use WebFont',
149 'description' => 'Load fonts with WebFont.',
150 'accepted_value' => ['on', 'off'],
151 ],
152 'two_test_mode' => [
153 'type' => 'checkbox',
154 'default' => '',
155 'tab' => 'general',
156 'title' => 'Enable test mode',
157 'description' => 'Enable test mode to disable optimization for live site. Add ?twbooster=1 to urls to load optimized pages.',
158 'accepted_value' => ['on', 'off'],
159 ],
160 'two_files_cache' => [
161 'type' => 'checkbox',
162 'default' => '',
163 'tab' => 'general',
164 'title' => 'Cache generated static files',
165 'description' => 'Enable this option to reuse generated static files for every request and speed up page loading speed',
166 'accepted_value' => ['on', 'off'],
167 ],
168 'two_enable_htaccess_caching_headers' => [
169 'type' => 'checkbox',
170 'default' => '',
171 'tab' => 'general',
172 'title' => 'Write caching headers in .htaccess',
173 'description' => 'Enable this option to write recommended caching headers in .htaccess file',
174 'accepted_value' => ['on', 'off'],
175 ],
176 'two_enable_plugin_autoupdate' => [
177 'type' => 'checkbox',
178 'default' => '',
179 'tab' => 'general',
180 'title' => 'Enable plugin autoupdate',
181 'description' => 'When checked, Wordpress will autoupdate this plugin.',
182 'accepted_value' => ['on', 'off'],
183 ],
184 'two_all_pages_are_optimizable' => [
185 'type' => 'checkbox',
186 'default' => '',
187 'tab' => 'general',
188 'title' => 'Run Optimizer on every page',
189 'description' => 'Enable this option to run optimizer on every page, except excluded.',
190 'accepted_value' => ['on', 'off'],
191 ],
192 'two_optimize_archive_pages' => [
193 'type' => 'checkbox',
194 'default' => '',
195 'tab' => 'general',
196 'title' => 'Run Optimizer on archive pages',
197 'description' => 'Enable this option to run Optimizer on archive pages.',
198 'accepted_value' => ['on', 'off'],
199 ],
200 'two_connected' => [
201 'type' => 'txt',
202 'default' => '0',
203 'tab' => 'general',
204 'title' => '',
205 'description' => ''
206 ],
207 'cloudflare_cache_status' => [
208 'type' => 'checkbox',
209 'default' => 'off',
210 'tab' => 'general',
211 'title' => 'Cloudflare cache status',
212 'description' => '',
213 'accepted_value' => ['on', 'off'],
214 ],
215 'two_change_minify' => [
216 'type' => 'checkbox',
217 'default' => '',
218 'tab' => 'general',
219 'title' => 'Minify library type',
220 'values' => ['JSMin' => 'JSMin', 'Minify' => 'Minify'],
221 'description' => '',
222 'accepted_value' => ['JSMin', 'Minify'],
223 ],
224 /*End general*/
225
226 /*Start css*/
227 'two_aggregate_css' => [
228 'type' => 'checkbox',
229 'default' => 'on',
230 'tab' => 'css',
231 'title' => 'CSS aggregation',
232 'description' => 'Enable or disable the aggregation of your CSS files. By aggregating your CSS, all your stylesheets are combined into one, <br>reducing the number of HTTP requests and speeding up your site.',
233 'accepted_value' => ['on', 'off'],
234 ],
235 'two_include_inline_css' => [
236 'type' => 'checkbox',
237 'default' => 'on',
238 'tab' => 'css',
239 'show' => ['two_aggregate_css' => 'on'],
240 'title' => 'Inline CSS extraction',
241 'description' => 'Enable this option to remove CSS styles from &lt;style&gt; tags and aggregate them in a separate file. <br>This can help with page load times and organization of your CSS.',
242 'accepted_value' => ['on', 'off'],
243 ],
244 'two_exclude_css' => [
245 'type' => 'textarea',
246 'default' => 'wp-content/cache/, admin-bar.min.css, ds-gravity-forms-for-divi, wvc-page-style-inline-css, wvc-theme',
247 'tab' => 'css',
248 'title' => 'Excluded CSS files',
249 'description' => 'Specify the CSS files that should be excluded from the optimization.',
250 'accepted_value' => 'string',
251 ],
252 'two_async_all' => [
253 'type' => 'checkbox',
254 'default' => 'off',
255 'tab' => 'css',
256 'title' => 'Async All CSS',
257 'description' => 'Enable this checkbox to async all css files.',
258 'accepted_value' => ['on', 'off'],
259 ],
260 'two_async_css' => [
261 'type' => 'textarea',
262 'default' => false,
263 'tab' => 'css',
264 'hide' => ['two_async_all' => 'on'],
265 'title' => 'Async CSS Files',
266 'description' => 'Mention the handles of the CSS files to load after the main site content is loaded. This is helpful when there are CSS files that can slow down the website.',
267 'accepted_value' => 'string',
268 ],
269 'two_disable_wp_dashicons' => [
270 'type' => 'checkbox',
271 'default' => 'off',
272 'tab' => 'css',
273 'title' => 'Disable dashicons',
274 'description' => 'Enable this checkbox to disable dashicons.css .',
275 'accepted_value' => ['on', 'off'],
276 ],
277 'two_add_overflow_to_page' => [
278 'type' => 'select',
279 'values' => ['off' => 'Disabled', 'body' => 'On body', 'html' => 'On HTML', 'body, html' => 'On body and HTML'],
280 'default' => 'off',
281 'tab' => 'css',
282 'title' => 'Fix website scroll issues',
283 'description' => 'If you’re encountering difficulties with the website’s scroll functionality please check the following options. <br>Depending on the unique specifics of your situation, one of these options should effectively resolve the issue.',
284 'accepted_value' => ['off', 'body', 'html', 'body, html'],
285 ],
286 'two_disable_css' => [
287 'type' => 'textarea',
288 'default' => false,
289 'tab' => 'css',
290 'title' => 'Disable CSS Files',
291 'description' => 'Disabled CSS Files Use this option to specify the CSS files that are not used and should be disabled from all pages of your website.',
292 'accepted_value' => 'string',
293 ],
294 'two_minify_css' => [
295 'type' => 'checkbox',
296 'default' => 'on',
297 'tab' => 'css',
298 'title' => 'CSS minification',
299 'description' => 'Turn on this setting to reduce the size of your CSS files by removing unnecessary characters. <br>Please note, if you notice a substantial increase in your website\'s loading time (like 5x or more), try disabling this option.',
300 'accepted_value' => ['on', 'off'],
301 ],
302 'two_split_css' => [
303 'type' => 'checkbox',
304 'default' => '',
305 'tab' => 'css',
306 'title' => '',
307 'description' => '',
308 'not used' => true,
309 'accepted_value' => ['on', 'off'],
310 ],
311 /*End css*/
312
313 /*Start js*/
314 'two_aggregate_js' => [
315 'type' => 'checkbox',
316 'default' => 'on',
317 'tab' => 'js',
318 'hide' => ['two_delay_all_js_execution' => 'on'],
319 'title' => 'JavaScript aggregation',
320 'description' => 'Use this setting to enable or disable the aggregation of your JavaScript files. By bundling your JS files together, the number <br>of server requests can be reduced, potentially improving your site\'s performance.',
321 'accepted_value' => ['on', 'off'],
322 ],
323 'two_include_inline_js' => [
324 'type' => 'checkbox',
325 'default' => 'on',
326 'tab' => 'js',
327 'hide' => ['two_delay_all_js_execution' => 'on', 'two_aggregate_js' => 'off'],
328 'title' => 'Include inline JS',
329 'description' => 'Check this option to include the internal JS scripts of your web pages in the optimization.',
330 'accepted_value' => ['on', 'off'],
331 ],
332
333 'two_use_extended_exception_list_js' => [
334 'type' => 'checkbox',
335 'default' => '',
336 'tab' => 'js',
337 'hide' => ['two_delay_all_js_execution' => 'on'],
338 'title' => 'Use extended exception list for inline script aggregation',
339 'description' => 'Check this option to exclude more internal scripts from optimization.',
340 'accepted_value' => ['on', 'off'],
341 ],
342 'two_dequeue_jquery_migrate' => [
343 'type' => 'checkbox',
344 'default' => '',
345 'tab' => 'js',
346 'hide' => ['two_delay_all_js_execution' => 'on'],
347 'title' => 'Remove jQuery Migrate',
348 'description' => 'Enable this checkbox to stop loading jquery-migrate.js file.',
349 'accepted_value' => ['on', 'off'],
350 ],
351
352 'two_exclude_delay_js' => [
353 'type' => 'textarea',
354 'default' => '',
355 'tab' => 'js',
356 'hide' => ['two_delay_all_js_execution' => 'on'],
357 'title' => 'Excluded JavaScript files',
358 'description' => 'Provide URLs or keywords to specify which inline or JavaScript files should be excluded from delayed execution.',
359 'accepted_value' => 'string',
360 ],
361 'two_delay_custom_js_new' => [
362 'type' => 'textarea',
363 'default' => false,
364 'tab' => 'js',
365 'hide' => ['two_delay_all_js_execution' => 'on'],
366 'title' => 'Include inline JS',
367 'description' => 'Check this option to include the internal JS scripts of your web pages in the optimization.',
368 'accepted_value' => 'string',
369 ],
370
371 'two_delay_js_execution' => [
372 'type' => 'checkbox',
373 'default' => '',
374 'tab' => 'js',
375 'hide' => ['two_delay_all_js_execution' => 'on'],
376 'title' => 'Delay JS execution',
377 'description' => 'Enable this option to delay javascript execution',
378 'accepted_value' => ['on', 'off'],
379 ],
380 'two_delayed_js_load_libs_first' => [
381 'type' => 'checkbox',
382 'default' => '',
383 'tab' => 'js',
384 'hide' => ['two_delay_all_js_execution' => 'on', 'two_delay_js_execution' => 'off'],
385 'title' => 'Load delayed JS libraries first',
386 'description' => 'Prioritize loading delayed scripts over inline scripts.',
387 'accepted_value' => ['on', 'off'],
388 ],
389 'two_delayed_js_execution_list' => [
390 'type' => 'textarea',
391 'default' => false,
392 'tab' => 'js',
393 'hide' => ['two_delay_all_js_execution' => 'on', 'two_delay_js_execution' => 'off'],
394 'title' => 'Delay Scripts from Execution',
395 'description' => 'Use this textbox to specify JavaScript files to be delayed.',
396 'accepted_value' => 'string',
397 ],
398
399 'two_exclude_js' => [
400 'type' => 'textarea',
401 'default' => 'wp-content/cache/, wp-includes/js/dist/, wp-includes/js/tinymce/, jquery.js, jquery.min.js, jquery-migrate.min.js, jquery-migrate.js, jquery.mobile, jquery-mobile',
402 'tab' => 'js',
403 'hide' => ['two_delay_all_js_execution' => 'on'],
404 'title' => 'Excluded JavaScript files',
405 'description' => 'Provide URLs or keywords to specify which inline or JavaScript files should be excluded from JavaScript aggregation.',
406 'accepted_value' => 'string',
407 ],
408 'two_minify_js' => [
409 'type' => 'checkbox',
410 'default' => 'on',
411 'tab' => 'js',
412 'hide' => ['two_delay_all_js_execution' => 'on'],
413 'title' => 'JavaScript minification',
414 'description' => 'This option allows you to enable or disable JavaScript file minification, which can help speed up your site by reducing file size.',
415 'accepted_value' => ['on', 'off'],
416 ],
417 'two_delay_js_exclusions' => [
418 'type' => 'two_window_multiselect',
419 'default' => '',
420 'tab' => 'js',
421 'values' => '',
422 'show' => ['two_delay_all_js_execution' => 'on'],
423 'title' => 'One-click exclusions',
424 'description' => 'With JavaScript delay, certain elements might not show up or need time/user interaction to appear, like menus, sliders, or forms. Exclude these items from JavaScript Delay to resolve these issues.',
425 'subdescription' => 'Select the plugins/themes you would like to exclude:',
426 'accepted_value' => 'array',
427 ],
428
429 'two_delay_all_js_execution' => [
430 'type' => 'checkbox',
431 'default' => 'on',
432 'tab' => 'js',
433 'title' => 'JavaScript delay',
434 'description' => 'Prioritizes the website rendering, by delaying JavaScript files until user interaction (i.e. scroll, click)',
435 'accepted_value' => ['on', 'off'],
436 ],
437 'two_timeout_js_load' => [
438 'type' => 'checkbox',
439 'default' => '',
440 'tab' => 'js',
441 'show' => ['two_delay_all_js_execution' => 'on'],
442 'title' => 'Timeout to js load',
443 'description' => 'Timeout to js load',
444 'accepted_value' => ['on', 'off'],
445 ],
446 'two_load_excluded_js_via_worker' => [
447 'type' => 'checkbox',
448 'default' => '',
449 'tab' => 'js',
450 'show' => ['two_delay_all_js_execution' => 'on'],
451 'title' => 'Load excluded JS files via worker',
452 'description' => 'Load excluded JS files via worker and connect them immediately.',
453 'accepted_value' => ['on', 'off'],
454 ],
455 'two_load_excluded_js_normally' => [
456 'type' => 'textarea',
457 'default' => false,
458 'tab' => 'js',
459 'show' => ['two_delay_all_js_execution' => 'on'],
460 'title' => 'Excluded JS files via worker load',
461 'description' => 'Use this textbox to specify JavaScript files and exclude JS files via worker load.',
462 'accepted_value' => 'string',
463 ],
464 'two_events_after_load' => [
465 'type' => 'multiselect',
466 'default' => '',
467 'tab' => 'js',
468 'show' => ['two_delay_all_js_execution' => 'on'],
469 'title' => 'Events After Load',
470 'values' => ['DOMContentLoaded' => 'DOMContentLoaded', 'Load' => 'Load', 'Click' => 'Click'],
471 'description' => 'Events which are triggered after page load',
472 'accepted_value' => 'array',
473 ],
474 'two_disabled_delay_all_js_pages' => [
475 'type' => 'textarea',
476 'default' => false,
477 'tab' => 'js',
478 'show' => ['two_delay_all_js_execution' => 'on'],
479 'title' => 'Excluded delayed JS Pages',
480 'description' => 'Use this textbox to specify Pages and exclude them from the optimization.<br>
481 "^/[^.]+$" use this expression to exclude all pages except the homepage (w/o quotes)<br>
482 "^/$" use this expression to exclude homepage (w/o quotes)<br>
483 "^((?!red|green|blue).)*$" use this expression to exclude every string that not contains red, green or blue words (w/o quotes)<br>
484 add any subdirectory before the slash in expression (e.g. /wordpress/) if the site is in subdirectory.',
485 'accepted_value' => 'string',
486 ],
487
488 /*End js*/
489
490 /* Start lazyload*/
491 'two_lazyload' => [
492 'type' => 'checkbox',
493 'default' => 'on',
494 'tab' => 'lazyload',
495 'title' => 'Lazy load for images',
496 'description' => 'Enable this option to activate lazy loading for image elements.',
497 'accepted_value' => ['on', 'off'],
498 ],
499 'two_add_noscript' => [
500 'type' => 'checkbox',
501 'default' => '',
502 'title' => 'Add noscript tag to Lazy Load Images',
503 'description' => 'Disable this option if you want to not add noscript tag to lazy load images.',
504 'accepted_value' => ['on', 'off'],
505 ],
506 'two_lazyload_slider_images' => [
507 'type' => 'checkbox',
508 'default' => '',
509 'tab' => 'lazyload',
510 'title' => 'Lazy Load Slider Images',
511 'description' => 'Enable this option to activate lazy loading for images in sliders. May cause UI breaks.',
512 'accepted_value' => ['on', 'off'],
513 ],
514 'two_bg_lazyload' => [
515 'type' => 'checkbox',
516 'default' => 'on',
517 'tab' => 'lazyload',
518 'title' => 'Lazy load for background images',
519 'description' => 'Enable this option to activate lazy loading for background images.',
520 'accepted_value' => ['on', 'off'],
521 ],
522 'two_img_in_viewport_lazyload' => [
523 'type' => 'checkbox',
524 'default' => 'on',
525 'tab' => 'lazyload',
526 'title' => 'Lazy load for images that are not in the viewport',
527 'description' => 'This option activates lazy load for images and excludes images in the viewport. To get images list in the viewport, generate critical CSS.',
528 'accepted_value' => ['on', 'off'],
529 ],
530 'two_iframe_lazyload' => [
531 'type' => 'checkbox',
532 'default' => 'on',
533 'tab' => 'lazyload',
534 'title' => 'iFrame lazy loading',
535 'description' => 'Enable the lazy loading of iFrames. This means iFrames will not load until they\'re visible on the user\'s screen, <br>helping to speed up initial page load times.',
536 'accepted_value' => ['on', 'off'],
537 ],
538 'two_delay_iframe_lazyload' => [
539 'type' => 'checkbox',
540 'default' => '',
541 'tab' => 'lazyload',
542 'title' => 'Delay Lazy Load for Iframes',
543 'description' => 'Enable this option to activate delayed lazy loading for iframes on your website pages.',
544 'accepted_value' => ['on', 'off'],
545 ],
546 'two_elemrntor_video_iframe' => [
547 'type' => 'checkbox',
548 'default' => '',
549 'tab' => 'lazyload',
550 'title' => 'Elementor youtube block to iframe',
551 'description' => 'Enable this option for convert elementor youtube block to iframe.',
552 'accepted_value' => ['on', 'off'],
553 ],
554 'two_remove_elementor_lazyload' => [
555 'type' => 'checkbox',
556 'default' => 'on',
557 'tab' => 'lazyload',
558 'title' => 'Remove Elementor default lazyload',
559 'description' => 'Enable this option if you want to remove elementor default lazyload.'
560 ],
561 'two_youtube_vimeo_iframe_lazyload' => [
562 'type' => 'checkbox',
563 'default' => '',
564 'tab' => 'lazyload',
565 'title' => 'Replace Youtube, Vimeo Videos with Thumbnails',
566 'description' => 'Enable this option to lazy load youtube, vimeo videos until you click the thumbnail.',
567 'accepted_value' => ['on', 'off'],
568 ],
569 'two_video_lazyload' => [
570 'type' => 'checkbox',
571 'default' => 'on',
572 'tab' => 'lazyload',
573 'title' => 'Video lazy loading',
574 'description' => 'Enable video lazy loading to improve page speed. With this option enabled, videos won\'t load until they <br>become visible on screen.',
575 'accepted_value' => ['on', 'off'],
576 ],
577 'two_exclude_lazyload' => [
578 'type' => 'textarea',
579 'default' => '',
580 'tab' => 'lazyload',
581 'title' => 'Exclude from Lazy Load Images/Videos/Iframes',
582 'description' => 'Exclude Lazy Load Images Enter the image names or paths that should be excluded from lazy loading.',
583 'accepted_value' => 'string',
584 ],
585 'lazy_load_type' => [
586 'type' => 'select',
587 'default' => 'vanilla',
588 'tab' => 'lazyload',
589 'title' => 'Lazy load type',
590 'values' => ['browser' => 'Browser', 'vanilla' => 'Vanilla'],
591 'description' => 'Select lazy load type',
592 'accepted_value' => ['browser', 'vanilla'],
593 ],
594 /* End lazyload*/
595
596 /*Start images*/
597 'two_do_not_optimize_images' => [
598 'type' => 'checkbox',
599 'default' => '',
600 'tab' => 'images',
601 'title' => 'Do Not Optimize Images',
602 'description' => 'Enable this option to disable pagspeed module image optimization on your website homepage.',
603 'accepted_value' => ['on', 'off'],
604 ],
605 'two_enable_use_srcset' => [
606 'type' => 'checkbox',
607 'default' => 'on',
608 'tab' => 'images',
609 'title' => 'Enable responsive images',
610 'description' => 'Enable this option to use small images for mobile and tablet devices',
611 'accepted_value' => ['on', 'off'],
612 ],
613 'two_enable_nginx_webp_delivery' => [
614 'type' => 'checkbox',
615 'default' => 'on',
616 'tab' => 'images',
617 'title' => 'Deliver WebP images if available',
618 'description' => '',
619 'accepted_value' => ['on', 'off'],
620 //ToDo TENWEB_SO_HOSTED_ON_10WEB
621 ],
622 'two_enable_htaccess_webp_delivery' => [
623 'type' => 'checkbox',
624 'default' => 'on',
625 'tab' => 'images',
626 'title' => 'Deliver WebP images if available using rewrite rules.',
627 'description' => '',
628 'accepted_value' => ['on', 'off'],
629 ],
630 'two_enable_picture_webp_delivery' => [
631 'type' => 'checkbox',
632 'default' => '',
633 'tab' => 'images',
634 'title' => 'Deliver WebP images if available using <picture> tags.',
635 'description' => 'Each <img> will be replaced with a <picture> tag. Some themes may break, so make sure to verify that everything seems fine.',
636 'accepted_value' => ['on', 'off'],
637 ],
638 'two_exclude_images_for_optimize' => [
639 'type' => 'textarea',
640 'default' => '',
641 'tab' => 'images',
642 'title' => 'Exclude Images from Optimization',
643 'description' => 'Exclude Images for optimization Enter the image names or paths that should be excluded from pagespeed module optimization process.',
644 'accepted_value' => 'string',
645 ],
646 'two_serve_optimized_bg_image' => [
647 'type' => 'checkbox',
648 'default' => '',
649 'tab' => 'images',
650 'title' => 'Implement Optimized Background Images',
651 'description' => 'Enable this option to use small background images for mobile and tablet devices',
652 'accepted_value' => ['on', 'off'],
653 ],
654 /*End images*/
655
656 /*Start css_in_specific_page*/
657 'two_async_page' => [
658 'type' => 'string',
659 'default' => null,
660 'tab' => 'css_in_specific_page',
661 'title' => '',
662 'description' => '',
663 'do_not_render' => true,
664 ],
665 'two_disable_page' => [
666 'type' => 'string',
667 'default' => null,
668 'tab' => 'css_in_specific_page',
669 'title' => '',
670 'description' => '',
671 'do_not_render' => true,
672 ],
673 /*End css_in_specific_page*/
674
675 /*Start critical_css*/
676 'two_critical_pages' => [
677 'type' => 'array',
678 'default' => '',
679 'tab' => 'critical_css',
680 'title' => 'Critical pages',
681 'description' => ''
682 ],
683 'two_critical_sizes' => [
684 'type' => 'array',
685 'default' => '',
686 'tab' => 'critical_css',
687 'title' => 'Sizes for critical generation',
688 'description' => ''
689 ],
690 'two_critical_url_args' => [
691 'type' => 'txt',
692 'default' => 'PageSpeed=off&two_nooptimize=1&two_action=generating_critical_css',
693 'tab' => 'critical_css',
694 'title' => 'URL query arguments',
695 'description' => ''
696 ],
697 'two_critical_status' => [
698 'type' => 'checkbox',
699 'default' => 'true',
700 'tab' => 'critical_css',
701 'title' => 'Critical CSS',
702 'description' => 'Improves website performance by extracting the CSS above the fold.',
703 'accepted_value' => ['on', 'off'],
704 ],
705 'two_critical_remove' => [
706 'type' => 'txt',
707 'default' => 'false',
708 'tab' => 'critical_css',
709 'title' => 'Remove Critical css',
710 'description' => 'Enable this option to remove critical css after css load'
711 ],
712 'two_critical_font_status' => [
713 'type' => 'txt',
714 'default' => 'true',
715 'tab' => 'critical_css',
716 'title' => 'Critical fonts',
717 'description' => 'Enable this option for critical fonts'
718 ],
719 'two_font_actions' => [
720 'type' => 'select',
721 'default' => 'not_load',
722 'tab' => 'critical_css',
723 'title' => 'Font optimizer',
724 'values' => ['default' => 'No optimization', 'not_load' => 'High optimization', 'exclude_uncritical_fonts' => 'Low optimization'],
725 'description' => 'Use optimized font loading for your website.',
726 'accepted_value' => ['default', 'not_load', 'exclude_uncritical_fonts'],
727 ],
728 /*End critical_css*/
729 /*Start non_optimizable_pages*/
730 'two_non_optimizable_speed_optimizer_pages' => [
731 'type' => 'textarea',
732 'default' => '',
733 'tab' => 'non_optimizable_pages',
734 'title' => 'Non Optimizable Pages List',
735 'description' => 'Pages with such url\'s are non Optimizable, or we are not recommend to opimize them',
736 'do_not_render' => true,
737 'accepted_value' => 'string',
738 ],
739 /*End non_optimizable_pages*/
740 ];
741
742 public $default_settings = [
743 'two_delay_js_exclusions' => [],
744 'two_test_mode' => '',
745 'cloudflare_cache_status' => 'off',
746 'two_files_cache' => 'on',
747 'two_enable_htaccess_caching_headers' => '',
748 'two_enable_plugin_autoupdate' => '',
749 'two_generate_ccss_on_load' => [],
750 'two_include_inline_js' => 'on',
751 'two_include_inline_css' => 'on',
752 'two_exclude_js' => 'wp-content/cache/, wp-includes/js/dist/, wp-includes/js/tinymce/, jquery.js, jquery.min.js, ' .
753 'jquery-migrate.min.js, jquery-migrate.js, jquery.mobile, jquery-mobile',
754 'two_delay_js_execution' => 'on',
755 'two_delay_all_js_execution' => 'on',
756 'two_timeout_js_load' => '',
757 'two_load_excluded_js_via_worker' => '',
758 'two_load_excluded_js_normally' => '',
759 'two_events_after_load' => ['DOMContentLoaded', 'Load', 'Click'],
760 'two_exclude_css' => 'wp-content/cache/, admin-bar.min.css, ds-gravity-forms-for-divi, wvc-page-style-inline-css, wvc-theme',
761 'two_lazyload' => 'on',
762 'two_bg_lazyload' => 'on',
763 'two_add_noscript' => 'on',
764 'two_iframe_lazyload' => 'on',
765 'two_delay_iframe_lazyload' => '',
766 'two_video_lazyload' => 'on',
767 'two_serve_gzip' => 'on',
768 'two_img_in_viewport_lazyload' => 'on',
769 'two_page_cache_life_time' => 7 * 24 * 60 * 60,
770 'lazy_load_type' => 'vanilla',
771 'two_async_css' => 'elementor-icons-css, elementor-animations-css, elementor-icons-shared-0-css, ' .
772 'elementor-icons-fa-brands-css, elementor-icons-fa-solid-css ,elementor-icons-fa-regular-css, ' .
773 'tenweb-website-builder-theme-style-css, open-sans-css, font-awesome-css, bwg_googlefonts-css, ' .
774 'bwg_fonts-css, elementor-global-css, google-fonts-1-css, elementor-common-css, ' .
775 'wc-block-style-css, wp-block-library-css',
776 'two_async_font' => 'on',
777 'two_merge_google_font_faces' => '',
778 'two_aggregate_js' => 'on',
779 'two_enable_use_srcset' => 'on',
780 'two_aggregate_css' => 'on',
781 'two_minify_css' => 'on',
782 'two_minify_js' => 'on',
783 'two_serve_optimized_bg_image' => 'on',
784 'two_enable_nginx_webp_delivery' => 'on',
785 'two_enable_htaccess_webp_delivery' => 'on',
786 'two_disabled_speed_optimizer_pages' => 'robots.txt,.well-known',
787 'two_critical_status' => 'true',
788 'two_critical_remove' => 'false',
789 'two_critical_font_status' => 'true',
790 'two_font_actions' => 'not_load',
791 'two_add_overflow_to_page' => 'off',
792 'two_critical_url_args' => 'PageSpeed=off&two_nooptimize=1&two_action=generating_critical_css',
793 'two_critical_sizes' => [
794 'two_1617650538215' => [
795 'width' => '1920',
796 'height' => '800',
797 'media' => '@media screen and (min-width: 1920px)',
798 'uid' => 'two_1617650538215'
799 ],
800 'two_1617650549855' => [
801 'width' => '1500',
802 'height' => '800',
803 'media' => '@media screen and (min-width: 1500px) and (max-width: 1920px)',
804 'uid' => 'two_1617650549855'
805 ],
806 'two_1617650561871' => [
807 'width' => '1280',
808 'height' => '700',
809 'media' => '@media screen and (min-width: 1280px) and (max-width: 1500px)',
810 'uid' => 'two_1617650561871'
811 ],
812 'two_1617650582190' => [
813 'width' => '1024',
814 'height' => '600',
815 'media' => '@media screen and (min-width: 1024px) and (max-width: 1280px)',
816 'uid' => 'two_1617650582190'
817 ],
818 'two_1617650596079' => [
819 'width' => '768',
820 'height' => '500',
821 'media' => '@media screen and (min-width: 767px) and (max-width: 1024px)',
822 'uid' => 'two_1617650596079'
823 ],
824 'two_1617650611968' => [
825 'width' => '320',
826 'height' => '400',
827 'media' => '@media screen and (max-width: 767px)',
828 'uid' => 'two_1617650611968'
829 ],
830 ],
831 'two_non_optimizable_speed_optimizer_pages' => '/wp-admin/, /xmlrpc.php, wp-.*.php, feed, index.php, sitemap(_index)?.xml, /store.*,
832 /cart.*, /my-account.*, /checkout.*, /addons.*, well-known, acme-challenge',
833 ];
834
835 public $critical_default_options = [
836 'use_uncritical' => 'false',
837 'load_type' => 'async',
838 'wait_until' => 'load',
839 'default_sizes' => [],
840 ];
841
842 public $critical_options = [
843 'uncritical_load_types' => [
844 'async' => 'Async',
845 'on_interaction' => 'On interaction',
846 'not_load' => 'Do not load',
847 ],
848 'critical_wait_until' => [
849 'load' => 'load',
850 'domcontentloaded' => 'domcontentloaded',
851 'networkidle0' => 'networkidle0',
852 'networkidle2' => 'networkidle2',
853 ]
854 ];
855
856 public function __construct()
857 {
858 $this->init_settings();
859 $this->init_critical_defaults();
860
861 if (defined('JETPACK__VERSION')) {
862 $this->settings_names['two_disable_jetpack_optimization']['do_not_render'] = false;
863 }
864 }
865
866 public function get_settings($name = null, $default = false)
867 {
868 // OptimizerUtils::stripslashes_deep used instead of stripslashes_deep() because in advanced-cache mode
869 // stripslashes_deep() function does not exists
870 if (isset($name)) {
871 if (isset($this->two_settings[$name])) {
872 return OptimizerUtils::stripslashes_deep($this->two_settings[$name]);
873 } else {
874 if ('two_clear_cache_date' == $name && function_exists('get_option')) {
875 return get_option('two_clear_cache_date');
876 }
877
878 if ('two_webp_delivery_working' == $name && function_exists('get_option')) {
879 return get_option('two_webp_delivery_working');
880 }
881
882 if ('tenweb_so_version' == $name && function_exists('get_option')) {
883 return TENWEB_SO_VERSION;
884 }
885 }
886
887 return $default;
888 }
889
890 return OptimizerUtils::stripslashes_deep($this->two_settings);
891 }
892
893 public function set_settings($data)
894 {
895 foreach ($this->settings_names as $key => $val) {
896 if (isset($data[$key])) {
897 if (is_array($data[$key])) {
898 $this->two_settings[$key] = map_deep($data[$key], 'sanitize_text_field');
899 } else {
900 $checked = sanitize_text_field($data[ $key ]);
901 $this->two_settings[$key] = $this->maybe_change_server_configuration($key, isset($this->two_settings[$key]) ? $this->two_settings[$key] : '', $checked);
902 }
903 } else {
904 $this->two_settings[$key] = $this->maybe_change_server_configuration($key, isset($this->two_settings[$key]) ? $this->two_settings[$key] : '', '');
905 }
906 }
907
908 // Change critical pages to post meta and remove from settings.
909 if (isset($this->two_settings[ 'two_critical_pages' ]) && is_array($this->two_settings[ 'two_critical_pages' ])) {
910 $page_on_front = $this->update_setting('two_critical_pages', $this->two_settings[ 'two_critical_pages' ]);
911
912 // Homepage needs to be saved separately as it depends on "Your homepage displays" option.
913 if (!$page_on_front) {
914 unset($this->two_settings[ 'two_critical_pages' ]);
915 } else {
916 $this->two_settings[ 'two_critical_pages' ] = $page_on_front;
917 }
918 }
919 $this->two_settings['two_connected'] = '0';
920
921 if (\Tenweb_Authorization\Login::get_instance()->check_logged_in()) {
922 $this->two_settings['two_connected'] = '1';
923
924 $home_url_db = get_option('two_home_url', false);
925 $home_url = get_home_url();
926
927 if ($home_url_db !== $home_url) {
928 update_option('two_home_url', $home_url);
929
930 if ($home_url_db !== false) {
931 OptimizerUtils::update_site_state();
932 }
933 }
934 }
935 update_option('two_settings', json_encode($this->two_settings)); // phpcs:ignore
936 $this->init_settings();
937 }
938
939 public function update_setting($name, $value, $excludeCriticalRegeneration = false)
940 {
941 // Save all critical data as meta for other pages than front_page.
942 if ('two_critical_pages' == $name) {
943 if (is_array($value)) {
944 foreach ($value as $page_id => $critical) {
945 if (OptimizerUrl::isCriticalSavedInSettings($page_id)) {
946 continue;
947 }
948 update_post_meta($page_id, 'two_critical_pages', $critical);
949 unset($value[ $page_id ]);
950 }
951 }
952 }
953 $two_settings = $this->get_settings();
954
955 if (is_array($value)) {
956 $value = map_deep($value, 'sanitize_text_field');
957 } else {
958 $value = sanitize_text_field($value);
959 }
960 $this->maybe_clear_cache($name, isset ($two_settings[ $name ]) ? $two_settings[ $name ] : '', $value, $excludeCriticalRegeneration);
961 $two_settings[ $name ] = $this->maybe_change_server_configuration($name, isset ($two_settings[ $name ]) ? $two_settings[ $name ] : '', $value);
962 $two_settings['two_connected'] = '0';
963
964 if (\Tenweb_Authorization\Login::get_instance()->check_logged_in()) {
965 $two_settings['two_connected'] = '1';
966 }
967 update_option('two_settings', json_encode($two_settings)); // phpcs:ignore
968 $this->two_settings[$name] = $two_settings[ $name ];
969
970 return $value;
971 }
972
973 public function maybe_clear_cache($name, $old_value, $new_value, $excludeCriticalRegeneration = false)
974 {
975 if ('two_test_mode' == $name && $old_value != $new_value) {
976 OptimizerAdmin::clear_cache(false, true); //do not regenerate critical on test mode change
977 }
978 }
979
980 public function maybe_change_server_configuration($name, $old_value, $new_value)
981 {
982 if ($old_value != $new_value) {
983 $response = false;
984
985 if ('two_enable_nginx_webp_delivery' == $name || 'two_enable_htaccess_webp_delivery' == $name) {
986 if ('two_enable_nginx_webp_delivery' == $name) {
987 $response = $this->change_nginx_webp_delivery([ 'nginx_webp_delivery' => ('on' == $new_value ? 'enabled' : 'disabled') ]);
988 }
989
990 if ('two_enable_htaccess_webp_delivery' == $name && !TENWEB_SO_HOSTED_ON_NGINX) {
991 add_filter('get_two_enable_htaccess_webp_delivery', function () use ($new_value) {
992 return $new_value;
993 });
994 $response = $this->write_htaccess_configs();
995 }
996
997 if (false !== $response && (!isset($response[ 'status' ]) || 'success' != $response[ 'status' ])) {
998 add_filter('two_save_settings_message', function ($message) {
999 return $message . ' ' . __('WebP delivery could not be changed. Old value restored.', 'tenweb-speed-optimizer');
1000 });
1001 add_filter('two_save_settings_code', function ($code) {
1002 return 'nginx_webp_delivery';
1003 });
1004
1005 return $old_value;
1006 }
1007 }
1008
1009 if ('two_enable_htaccess_caching_headers' == $name) {
1010 if ('two_enable_htaccess_caching_headers' == $name && !TENWEB_SO_HOSTED_ON_NGINX) {
1011 add_filter('get_two_enable_htaccess_caching_headers', function () use ($new_value) {
1012 return $new_value;
1013 });
1014 $response = $this->write_htaccess_configs();
1015 }
1016
1017 if (false !== $response && (!isset($response[ 'status' ]) || 'success' != $response[ 'status' ])) {
1018 add_filter('two_save_settings_message', function ($message) {
1019 return $message . ' ' . __('.htaccess could not be changed. Old value restored.', 'tenweb-speed-optimizer');
1020 });
1021 add_filter('two_save_settings_code', function ($code) {
1022 return $code;
1023 });
1024
1025 return $old_value;
1026 }
1027 }
1028 }
1029
1030 return $new_value;
1031 }
1032
1033 public function change_nginx_webp_delivery($request_data)
1034 {
1035 try {
1036 $tenweb_domain_id = get_option('tenweb_domain_id');
1037 $response_data = null;
1038
1039 if (class_exists('Tenweb_Manager\Manager') && true === TenwebServices::manager_ready() && isset($tenweb_domain_id)) {
1040 $response = TenwebServices::do_request(TENWEB_API_URL . '/domains/' . $tenweb_domain_id . '/set-nginx-webp-delivery', [
1041 'body' => $request_data,
1042 'method' => 'POST',
1043 'blocking' => true
1044 ]);
1045
1046 if (!is_wp_error($response) && 200 === wp_remote_retrieve_response_code($response)) {
1047 $response_data = [
1048 'status' => 'success',
1049 ];
1050 }
1051 } else {
1052 $response_data = [
1053 'status' => 'error',
1054 'error' => 'Tenweb Manager not ready'
1055 ];
1056 }
1057 } catch (Exception $e) {
1058 $response_data = [
1059 'status' => 'error',
1060 'error' => $e->getMessage()
1061 ];
1062 }
1063
1064 return $response_data;
1065 }
1066
1067 public function write_htaccess_configs()
1068 {
1069 try {
1070 $response_data = null;
1071
1072 if (TENWEB_SO_HTACCESS_WRITABLE && !TENWEB_SO_HOSTED_ON_NGINX) {
1073 /* Add rules to .htaccess */
1074 if (!function_exists('insert_with_markers')) {
1075 require_once ABSPATH . 'wp-admin/includes/misc.php';
1076 }
1077 $success = insert_with_markers(get_home_path() . '.htaccess', 'Speed Optimizer by 10Web', '');
1078 $insertion = $this->get_htaccess_webp_delivery();
1079 $insertion .= $this->get_htaccess_caching_headers();
1080 $success = insert_with_markers(get_home_path() . '.htaccess', 'Speed Optimizer by 10Web', $insertion);
1081
1082 if ($success) {
1083 $response_data = [
1084 'status' => 'success',
1085 ];
1086 }
1087 } else {
1088 $response_data = [
1089 'status' => 'error',
1090 'error' => 'htaccess is not writable'
1091 ];
1092 }
1093 } catch (Exception $e) {
1094 $response_data = [
1095 'status' => 'error',
1096 'error' => $e->getMessage()
1097 ];
1098 }
1099
1100 return $response_data;
1101 }
1102
1103 public function get_htaccess_webp_delivery()
1104 {
1105 $insertion = '';
1106 $enable_webp_delivery = apply_filters('get_two_enable_htaccess_webp_delivery', $this->get_settings('two_enable_htaccess_webp_delivery'));
1107
1108 if ('on' == $enable_webp_delivery && !OptimizerUtils::testWebPDelivery()) {
1109 $insertion = '
1110 <IfModule mod_rewrite.c>
1111 RewriteEngine On
1112
1113 # Does browser explicitly support webp?
1114 RewriteCond %{HTTP_USER_AGENT} Chrome [OR]
1115 # OR Is request from Page Speed
1116 RewriteCond %{HTTP_USER_AGENT} "Google Page Speed Insights" [OR]
1117 # OR does this browser explicitly support webp
1118 RewriteCond %{HTTP_ACCEPT} image/webp
1119 # AND NOT MS EDGE 42/17 - doesnt work.
1120 RewriteCond %{HTTP_USER_AGENT} !Edge/17
1121 # AND is the request a jpg, png or gif?
1122 RewriteCond %{REQUEST_URI} ^(.+)\.(?:jpe?g|png|gif)$
1123 # AND does a .ext.webp image exist?
1124 RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}.webp -f
1125 # THEN send the webp image and set the env var webp
1126 RewriteRule ^(.+)$ $1.webp [NC,T=image/webp,E=webp,L]
1127 </IfModule>
1128
1129 <IfModule mod_headers.c>
1130 # If REDIRECT_webp env var exists, append Accept to the Vary header
1131 Header append Vary Accept env=REDIRECT_webp
1132 </IfModule>
1133
1134 <IfModule mod_mime.c>
1135 AddType image/webp .webp
1136 </IfModule>
1137 ';
1138 }
1139
1140 return $insertion;
1141 }
1142
1143 public function get_htaccess_caching_headers()
1144 {
1145 $insertion = PHP_EOL;
1146 $enable_htaccess_caching_headers = apply_filters('get_two_enable_htaccess_caching_headers', $this->get_settings('two_enable_htaccess_caching_headers'));
1147
1148 if ('on' == $enable_htaccess_caching_headers) {
1149 $insertion .= $this->get_htaccess_charset();
1150 $insertion .= $this->get_htaccess_etag();
1151 $insertion .= $this->get_htaccess_web_fonts_access();
1152 $insertion .= $this->get_htaccess_files_match();
1153 $insertion .= $this->get_htaccess_mod_expires();
1154 $insertion .= $this->get_htaccess_mod_deflate();
1155 }
1156
1157 return $insertion;
1158 }
1159
1160 public function get_htaccess_charset()
1161 {
1162 // Get charset of the blog.
1163 $charset = preg_replace('/[^a-zA-Z0-9_\-\.:]+/', '', get_bloginfo('charset', 'display'));
1164
1165 if (empty($charset)) {
1166 return '';
1167 }
1168
1169 $rules = "# Use $charset encoding for anything served text/plain or text/html" . PHP_EOL;
1170 $rules .= "AddDefaultCharset $charset" . PHP_EOL;
1171 $rules .= "# Force $charset for a number of file formats" . PHP_EOL;
1172 $rules .= '<IfModule mod_mime.c>' . PHP_EOL;
1173 $rules .= "AddCharset $charset .atom .css .js .json .rss .vtt .xml" . PHP_EOL;
1174 $rules .= '</IfModule>' . PHP_EOL . PHP_EOL;
1175
1176 return $rules;
1177 }
1178
1179 public function get_htaccess_etag()
1180 {
1181 $rules = '# FileETag None is not enough for every server.' . PHP_EOL;
1182 $rules .= '<IfModule mod_headers.c>' . PHP_EOL;
1183 $rules .= 'Header unset ETag' . PHP_EOL;
1184 $rules .= '</IfModule>' . PHP_EOL . PHP_EOL;
1185 $rules .= '# Since we’re sending far-future expires, we don’t need ETags for static content.' . PHP_EOL;
1186 $rules .= '# developer.yahoo.com/performance/rules.html#etags' . PHP_EOL;
1187 $rules .= 'FileETag None' . PHP_EOL . PHP_EOL;
1188
1189 return $rules;
1190 }
1191
1192 public function get_htaccess_web_fonts_access()
1193 {
1194 $rules = '# Send CORS headers if browsers request them; enabled by default for images.' . PHP_EOL;
1195 $rules .= '<IfModule mod_setenvif.c>' . PHP_EOL;
1196 $rules .= '<IfModule mod_headers.c>' . PHP_EOL;
1197 $rules .= '# mod_headers, y u no match by Content-Type?!' . PHP_EOL;
1198 $rules .= '<FilesMatch "\.(avifs?|cur|gif|png|jpe?g|svgz?|ico|webp)$">' . PHP_EOL;
1199 $rules .= 'SetEnvIf Origin ":" IS_CORS' . PHP_EOL;
1200 $rules .= 'Header set Access-Control-Allow-Origin "*" env=IS_CORS' . PHP_EOL;
1201 $rules .= '</FilesMatch>' . PHP_EOL;
1202 $rules .= '</IfModule>' . PHP_EOL;
1203 $rules .= '</IfModule>' . PHP_EOL . PHP_EOL;
1204
1205 $rules .= '# Allow access to web fonts from all domains.' . PHP_EOL;
1206 $rules .= '<FilesMatch "\.(eot|otf|tt[cf]|woff2?)$">' . PHP_EOL;
1207 $rules .= '<IfModule mod_headers.c>' . PHP_EOL;
1208 $rules .= 'Header set Access-Control-Allow-Origin "*"' . PHP_EOL;
1209 $rules .= '</IfModule>' . PHP_EOL;
1210 $rules .= '</FilesMatch>' . PHP_EOL . PHP_EOL;
1211
1212 return $rules;
1213 }
1214
1215 public function get_htaccess_files_match()
1216 {
1217 $rules = '<IfModule mod_alias.c>' . PHP_EOL;
1218 $rules .= '<FilesMatch "\.(html|htm|rtf|rtx|txt|xsd|xsl|xml)$">' . PHP_EOL;
1219 $rules .= '<IfModule mod_headers.c>' . PHP_EOL;
1220 $rules .= 'Header set X-Powered-By "TenWeb Speed Optimizer"' . PHP_EOL;
1221 $rules .= 'Header unset Pragma' . PHP_EOL;
1222 $rules .= 'Header append Cache-Control "public"' . PHP_EOL;
1223 $rules .= 'Header unset Last-Modified' . PHP_EOL;
1224 $rules .= '</IfModule>' . PHP_EOL;
1225 $rules .= '</FilesMatch>' . PHP_EOL . PHP_EOL;
1226 $rules .= '<FilesMatch "\.(css|htc|js|asf|asx|wax|wmv|wmx|avi|bmp|class|divx|doc|docx|eot|exe|gif|gz|gzip|ico|jpg|jpeg|jpe|json|mdb|mid|midi|mov|qt|mp3|m4a|mp4|m4v|mpeg|mpg|mpe|mpp|otf|odb|odc|odf|odg|odp|ods|odt|ogg|pdf|png|pot|pps|ppt|pptx|ra|ram|svg|svgz|swf|tar|tif|tiff|ttf|ttc|wav|wma|wri|xla|xls|xlsx|xlt|xlw|zip)$">' . PHP_EOL;
1227 $rules .= '<IfModule mod_headers.c>' . PHP_EOL;
1228 $rules .= 'Header unset Pragma' . PHP_EOL;
1229 $rules .= 'Header append Cache-Control "public"' . PHP_EOL;
1230 $rules .= '</IfModule>' . PHP_EOL;
1231 $rules .= '</FilesMatch>' . PHP_EOL;
1232 $rules .= '</IfModule>' . PHP_EOL . PHP_EOL;
1233
1234 return $rules;
1235 }
1236
1237 public function get_htaccess_mod_expires()
1238 {
1239 $rules = <<<HTACCESS
1240 <IfModule mod_mime.c>
1241 AddType image/avif avif
1242 AddType image/avif-sequence avifs
1243 </IfModule>
1244 # Expires headers (for better cache control)
1245 <IfModule mod_expires.c>
1246 ExpiresActive on
1247 ExpiresDefault "access plus 1 month"
1248 # cache.appcache needs re-requests in FF 3.6 (thanks Remy ~Introducing HTML5)
1249 ExpiresByType text/cache-manifest "access plus 0 seconds"
1250 # Your document html
1251 ExpiresByType text/html "access plus 0 seconds"
1252 # Data
1253 ExpiresByType text/xml "access plus 0 seconds"
1254 ExpiresByType application/xml "access plus 0 seconds"
1255 ExpiresByType application/json "access plus 0 seconds"
1256 # Feed
1257 ExpiresByType application/rss+xml "access plus 1 hour"
1258 ExpiresByType application/atom+xml "access plus 1 hour"
1259 # Favicon (cannot be renamed)
1260 ExpiresByType image/x-icon "access plus 1 week"
1261 # Media: images, video, audio
1262 ExpiresByType image/gif "access plus 4 months"
1263 ExpiresByType image/png "access plus 4 months"
1264 ExpiresByType image/jpeg "access plus 4 months"
1265 ExpiresByType image/webp "access plus 4 months"
1266 ExpiresByType video/ogg "access plus 4 months"
1267 ExpiresByType audio/ogg "access plus 4 months"
1268 ExpiresByType video/mp4 "access plus 4 months"
1269 ExpiresByType video/webm "access plus 4 months"
1270 ExpiresByType image/avif "access plus 4 months"
1271 ExpiresByType image/avif-sequence "access plus 4 months"
1272 # HTC files (css3pie)
1273 ExpiresByType text/x-component "access plus 1 month"
1274 # Webfonts
1275 ExpiresByType font/ttf "access plus 4 months"
1276 ExpiresByType font/otf "access plus 4 months"
1277 ExpiresByType font/woff "access plus 4 months"
1278 ExpiresByType font/woff2 "access plus 4 months"
1279 ExpiresByType image/svg+xml "access plus 4 months"
1280 ExpiresByType application/vnd.ms-fontobject "access plus 1 month"
1281 # CSS and JavaScript
1282 ExpiresByType text/css "access plus 1 year"
1283 ExpiresByType application/javascript "access plus 1 year"
1284 </IfModule>
1285
1286 HTACCESS;
1287
1288 return $rules;
1289 }
1290
1291 public function get_htaccess_mod_deflate()
1292 {
1293 $rules = '# Gzip compression' . PHP_EOL;
1294 $rules .= '<IfModule mod_deflate.c>' . PHP_EOL;
1295 $rules .= '# Active compression' . PHP_EOL;
1296 $rules .= 'SetOutputFilter DEFLATE' . PHP_EOL;
1297 $rules .= '# Force deflate for mangled headers' . PHP_EOL;
1298 $rules .= '<IfModule mod_setenvif.c>' . PHP_EOL;
1299 $rules .= '<IfModule mod_headers.c>' . PHP_EOL;
1300 $rules .= 'SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s*,?\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding' . PHP_EOL;
1301 $rules .= 'RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding' . PHP_EOL;
1302 $rules .= '# Don’t compress images and other uncompressible content' . PHP_EOL;
1303 $rules .= 'SetEnvIfNoCase Request_URI \\' . PHP_EOL;
1304 $rules .= '\\.(?:gif|jpe?g|png|rar|zip|exe|flv|mov|wma|mp3|avi|swf|mp?g|mp4|webm|webp|pdf)$ no-gzip dont-vary' . PHP_EOL;
1305 $rules .= '</IfModule>' . PHP_EOL;
1306 $rules .= '</IfModule>' . PHP_EOL . PHP_EOL;
1307 $rules .= '# Compress all output labeled with one of the following MIME-types' . PHP_EOL;
1308 $rules .= '<IfModule mod_filter.c>' . PHP_EOL;
1309 $rules .= 'AddOutputFilterByType DEFLATE application/atom+xml \
1310 application/javascript \
1311 application/json \
1312 application/rss+xml \
1313 application/vnd.ms-fontobject \
1314 application/x-font-ttf \
1315 application/xhtml+xml \
1316 application/xml \
1317 font/opentype \
1318 image/svg+xml \
1319 image/x-icon \
1320 text/css \
1321 text/html \
1322 text/plain \
1323 text/x-component \
1324 text/xml' . PHP_EOL;
1325 $rules .= '</IfModule>' . PHP_EOL;
1326 $rules .= '<IfModule mod_headers.c>' . PHP_EOL;
1327 $rules .= 'Header append Vary: Accept-Encoding' . PHP_EOL;
1328 $rules .= '</IfModule>' . PHP_EOL;
1329 $rules .= '</IfModule>' . PHP_EOL . PHP_EOL;
1330
1331 return $rules;
1332 }
1333
1334 public function set_default_settings()
1335 {
1336 if (!TENWEB_SO_HOSTED_ON_10WEB) {
1337 $this->default_settings['two_page_cache'] = 'on';
1338 }
1339
1340 if (class_exists('RevSliderFront') || is_plugin_active('revslider/revslider.php')) {
1341 $this->default_settings['two_delay_js_exclusions'][] = 'revslider';
1342 }
1343
1344 if (class_exists('WDS') || is_plugin_active('slider-wd/slider-wd.php')) {
1345 $this->default_settings['two_delay_js_exclusions'][] = 'slider-wd';
1346 }
1347
1348 if (class_exists('BWG') || is_plugin_active('photo-gallery/photo-gallery.php')) {
1349 $this->default_settings['two_delay_js_exclusions'][] = 'photo-gallery';
1350 }
1351
1352 if (defined('JETPACK__VERSION') || is_plugin_active('jetpack/jetpack.php')) {
1353 $this->default_settings['two_disable_jetpack_optimization'] = 'on';
1354 }
1355
1356 $builder_type = OptimizerUtils::detect_builder_type();
1357
1358 if ($builder_type === 'wvc') {
1359 $this->default_settings['two_delay_all_js_execution'] = '';
1360 }
1361
1362 if (TWO_ALWAYS_CRITICAL && !TENWEB_SO_HOSTED_ON_10WEB) {
1363 $this->default_settings['two_generate_ccss_on_load'] = ['page'];
1364 }
1365 $this->set_settings($this->default_settings);
1366 $this->init_settings();
1367 }
1368
1369 public function init_critical_defaults()
1370 {
1371 if (function_exists('get_option')) {
1372 $two_critical_default_settings = get_option('two_critical_default_settings');
1373
1374 if (empty($two_critical_default_settings)) {
1375 $two_critical_sizes = $this->get_settings('two_critical_sizes');
1376
1377 if ($two_critical_sizes === false || !is_array($two_critical_sizes)) {
1378 $two_critical_sizes = $this->default_settings['two_critical_sizes'];
1379 }
1380
1381 $this->critical_default_options['default_sizes'] = array_keys($two_critical_sizes);
1382 update_option('two_critical_default_settings', $this->critical_default_options);
1383 }
1384 }
1385 }
1386
1387 public function set_critical_defaults($page_defaults = false)
1388 {
1389 $this->update_setting('two_critical_url_args', $this->default_settings['two_critical_url_args']);
1390 $this->update_setting('two_critical_sizes', $this->default_settings['two_critical_sizes']);
1391 }
1392
1393 /**
1394 * @return false|string
1395 *
1396 * @throws JsonException
1397 */
1398 public function export_settings()
1399 {
1400 $two_settings = get_option('two_settings');
1401
1402 if (OptimizerUtils::isJson($two_settings)) {
1403 $two_settings = json_decode($two_settings, true);
1404 }
1405 $current_date = date('Y-m-d'); // phpcs:ignore
1406 $file_data = [
1407 'version' => TENWEB_SO_VERSION,
1408 'date' => $current_date,
1409 'settings' => $two_settings
1410 ];
1411
1412 return json_encode($file_data); // phpcs:ignore
1413 }
1414
1415 public function import_settings($filepath)
1416 {
1417 if (file_exists($filepath) && is_readable($filepath)) {
1418 $json_data = file_get_contents($filepath); // phpcs:ignore
1419 $data_arr = json_decode($json_data, true);
1420
1421 if (!empty($data_arr['settings'])) {
1422 if (isset($data_arr['settings']['two_enable_nginx_webp_delivery'])) {
1423 $data_arr[ 'settings' ][ 'two_enable_nginx_webp_delivery' ] = $this->maybe_change_server_configuration('two_enable_nginx_webp_delivery', $this->two_settings[ 'two_enable_nginx_webp_delivery' ], $data_arr[ 'settings' ][ 'two_enable_nginx_webp_delivery' ]);
1424 }
1425
1426 if (isset($data_arr['settings']['two_enable_htaccess_webp_delivery'])) {
1427 $data_arr[ 'settings' ][ 'two_enable_htaccess_webp_delivery' ] = $this->maybe_change_server_configuration('two_enable_htaccess_webp_delivery', $this->two_settings[ 'two_enable_htaccess_webp_delivery' ], $data_arr[ 'settings' ][ 'two_enable_htaccess_webp_delivery' ]);
1428 }
1429 update_option('two_settings', json_encode($data_arr['settings'])); // phpcs:ignore
1430
1431 return true;
1432 }
1433 }
1434
1435 return false;
1436 }
1437
1438 private function init_settings()
1439 {
1440 if (!function_exists('get_option') && defined('TENWEB_SO_ADVANCED_CACHE') && TENWEB_SO_ADVANCED_CACHE) {
1441 $two_settings = WebPageCache\OptimizerWebPageCache::get_config('two_settings');
1442
1443 if (isset($two_settings) && $two_settings !== false) {
1444 $this->two_settings = json_decode($two_settings, true);
1445 }
1446 } else {
1447 $two_settings = get_option('two_settings');
1448 $two_settings = json_decode($two_settings, true);
1449 $no_optimize_pages_list = get_option('no_optimize_pages');
1450 $two_settings['no_optimize_pages'] = $no_optimize_pages_list;
1451 $two_settings = json_encode($two_settings); // phpcs:ignore
1452 $this->settings_names['two_delay_js_exclusions']['values'] = ExcludeJsFromDelay::get_exclusion_data();
1453
1454 if ($two_settings !== false) {
1455 $this->two_settings = json_decode($two_settings, true);
1456 } else {
1457 foreach ($this->settings_names as $key => $val) {
1458 $this->two_settings[$key] = get_option($key);
1459 }
1460 $no_optimize_pages_list = get_option('no_optimize_pages');
1461 $this->two_settings['no_optimize_pages'] = $no_optimize_pages_list;
1462 }
1463
1464 /*for backward compatible Exclude plugins from delay*/
1465 $backward_compatible_list = [
1466 'two_exclude_rev' => ['two_645cf48d457e0_92d14020733d85d20a6f51a46a38872d'],
1467 'two_exclude_slider_by_10web' => ['two_645cf48d457dd_8e3dd77550d6ece1134867f5dc6c1fdb'],
1468 'two_exclude_elementor_scripts' => [
1469 'two_645cf48d457d4_47d522d3cb4abfa9a623d0c21864356e',
1470 'two_645cf48d457db_9334f340c1ba58bf54ed37d3898dd99f',
1471 ],
1472 'two_exclude_photo_gallery_by_10web' => ['two_645cf48d457de_35963ef4440c295121f3955c1d4c6e3f'],
1473 'two_exclude_amp_plugin_cdn' => ['two_645cf48d457df_162cacf0d591b432412c89437dea28e0'],
1474 'two_exclude_owl' => ['two_645cf3b5af449_3cc56afd5dcfa3a620c6f75c2d1befb8'],
1475 'two_exclude_slick' => ['two_645cf3b5af45e_0826a5ad820ef3bf2bd5528da35a7b78'],
1476 'two_exclude_google_ads' => ['two_645cf3b5af461_5e39a03248f0c1c99a1594e2a5fcdf13'],
1477 ];
1478
1479 if (!isset($this->two_settings['two_delay_js_exclusions']) || !is_array($this->two_settings['two_delay_js_exclusions'])) {
1480 $this->two_settings['two_delay_js_exclusions'] = [];
1481 }
1482
1483 foreach ($backward_compatible_list as $key => $val) {
1484 if (isset($this->two_settings[$key]) && $this->two_settings[$key] === 'on') {
1485 $this->two_settings['two_delay_js_exclusions'][] = $val;
1486 }
1487 $this->update_setting($key, '');
1488 }
1489 $this->two_settings['two_delay_js_exclusions'] = OptimizerUtils::two_flatten($this->two_settings['two_delay_js_exclusions']);
1490
1491 $this->update_setting('two_delay_js_exclusions', $this->two_settings['two_delay_js_exclusions']);
1492 /*end*/
1493 }
1494
1495 if (isset($this->two_settings['lazy_load_type']) && $this->two_settings['lazy_load_type'] !== 'vanilla') {
1496 $this->two_settings['two_bg_lazyload'] = '';
1497 }
1498 }
1499
1500 public static function get_instance()
1501 {
1502 if (null == self::$instance) {
1503 self::$instance = new self();
1504 }
1505
1506 return self::$instance;
1507 }
1508
1509 public function setTestMode($html)
1510 {
1511 update_option('two_test_mode', $html, 'no');
1512
1513 return true;
1514 }
1515
1516 public function getTestMode()
1517 {
1518 return get_option('two_test_mode', false);
1519 }
1520
1521 public function removeTestMode()
1522 {
1523 delete_option('two_test_mode');
1524
1525 return true;
1526 }
1527
1528 public function sync_configs_with_plugin_state($plugin_state = 'active')
1529 {
1530 if ('active' === $plugin_state) {
1531 if (TENWEB_SO_HOSTED_ON_10WEB) {
1532 $enable_webp_delivery = $this->get_settings('two_enable_nginx_webp_delivery');
1533 $this->change_nginx_webp_delivery([ 'nginx_webp_delivery' => ('on' == $enable_webp_delivery ? 'enabled' : 'disabled') ]);
1534 } elseif (!TENWEB_SO_HOSTED_ON_NGINX) {
1535 add_filter('get_two_enable_htaccess_webp_delivery', function () {
1536 return $this->get_settings('two_enable_htaccess_webp_delivery');
1537 });
1538 $this->write_htaccess_configs();
1539 }
1540
1541 if ('on' === $this->get_settings('two_page_cache')) {
1542 \TenWebOptimizer\WebPageCache\OptimizerWebPageCacheWP::get_instance()->store_page_cache_configs();
1543 \TenWebOptimizer\WebPageCache\OptimizerWebPageCacheWP::get_instance()->enable_page_cache();
1544 }
1545 } else {
1546 if (TENWEB_SO_HOSTED_ON_10WEB) {
1547 $this->change_nginx_webp_delivery([ 'nginx_webp_delivery' => ('disabled') ]);
1548 } elseif (!TENWEB_SO_HOSTED_ON_NGINX) {
1549 add_filter('get_two_enable_htaccess_webp_delivery', function () {
1550 return '';
1551 });
1552 $this->write_htaccess_configs();
1553 }
1554 \TenWebOptimizer\WebPageCache\OptimizerWebPageCacheWP::get_instance()->disable_page_cache();
1555 }
1556 }
1557
1558 public function get_default_setting($name)
1559 {
1560 return $this->default_settings[$name];
1561 }
1562 }
1563