PluginProbe
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance / 4.6.0
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance v4.6.0
4.7.0 4.6.1 4.6.0 4.5.5 4.5.4 4.5.3 4.5.2 3.2.20 3.2.21 3.2.22 3.2.3 3.2.5 3.2.6 3.2.7 3.2.9 3.3.0 3.3.1 3.3.2 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.7.0 3.7.1 All 111 releases
wp-optimize / includes / class-wp-optimize-admin.php

class-wp-optimize-admin.php in WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance 4.6.0, at includes/class-wp-optimize-admin.php

927 lines 36.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if (!defined('ABSPATH')) die('No direct access allowed');
3
4 if (!class_exists('WP_Optimize_Admin')) :
5 class WP_Optimize_Admin {
6
7 /**
8 * Class constructor
9 */
10 public function __construct() {
11 if (is_multisite()) {
12 add_action('network_admin_menu', array($this, 'admin_menu'));
13 } else {
14 add_action('admin_menu', array($this, 'admin_menu'));
15 }
16 add_action('admin_bar_menu', array($this, 'cache_admin_bar'), 100, 1);
17 }
18
19 /**
20 * Returns singleton instance object
21 *
22 * @return WP_Optimize_Admin Returns `WP_Optimize_Admin` object
23 */
24 public static function instance() {
25 static $_instance = null;
26 if (empty($_instance)) {
27 $_instance = new self();
28 }
29 return $_instance;
30 }
31
32
33 /**
34 * Builds the Tabs that should be displayed
35 *
36 * @param string $page
37 *
38 * @return array Returns all tabs specified array
39 */
40 public function get_tabs($page) {
41 // define tabs for pages.
42 $pages_tabs = array(
43 'WP-Optimize' => array(
44 'optimize' => __('Optimizations', 'wp-optimize'),
45 'tables' => __('Tables', 'wp-optimize'),
46 'settings' => __('Settings', 'wp-optimize'),
47 'table_analysis' => __('Table usage', 'wp-optimize').'<span class="menu-pill premium-only">Premium</span>'
48 ),
49 'wpo_images' => array(
50 'smush' => __('Compress images', 'wp-optimize'),
51 'dimensions' => __('Images dimensions', 'wp-optimize').'<span class="menu-pill premium-only">Premium</span>',
52 'unused' => __('Unused images and sizes', 'wp-optimize').'<span class="menu-pill premium-only">Premium</span>',
53 'lazyload' => __('Lazy-load', 'wp-optimize').'<span class="menu-pill premium-only">Premium</span>',
54 ),
55 'wpo_cache' => array(
56 'cache' => __('Page cache', 'wp-optimize'),
57 'preload' => __('Preload', 'wp-optimize'),
58 'lcp' => __('Auto LCP', 'wp-optimize').'<span class="menu-pill premium-only">Premium</span>',
59 'advanced' => __('Advanced settings', 'wp-optimize'),
60 'gzip' => __('Gzip compression', 'wp-optimize'),
61 'settings' => __('Static file headers', 'wp-optimize') // Adds a settings tab
62 ),
63 'wpo_minify' => array(
64 "status" => __('Minify status', 'wp-optimize'),
65 "js" => __('JavaScript', 'wp-optimize').'<span class="menu-pill disabled hidden">'.__('Disabled', 'wp-optimize').'</span>',
66 "css" => __('CSS', 'wp-optimize').'<span class="menu-pill disabled hidden">'.__('Disabled', 'wp-optimize').'</span>',
67 "font" => __('Fonts', 'wp-optimize'),
68 "analytics" => __('Google Analytics', 'wp-optimize').'<span class="menu-pill premium-only">Premium</span>',
69 "settings" => __('Settings', 'wp-optimize'),
70 "preload" => __('Preload', 'wp-optimize'),
71 "advanced" => __('Advanced', 'wp-optimize')
72 ),
73 'wpo_performance' => array(
74 '404_detector' => __('Not found requests', 'wp-optimize'),
75 ),
76 'wpo_settings' => array(
77 'settings' => array(
78 'title' => __('Settings', 'wp-optimize'),
79 ),
80 // 'updraftcentral' => array(
81 // 'title' => 'UpdraftCentral'
82 // ),
83 'status' => __('System status', 'wp-optimize'),
84 ),
85 'wpo_support' => array('support' => __('Support / FAQs', 'wp-optimize')),
86 'wpo_mayalso' => array('may_also' => __('Premium / Plugin family', 'wp-optimize')),
87 );
88
89 $tabs = (array_key_exists($page, $pages_tabs)) ? $pages_tabs[$page] : array();
90 $filtered_tabs = apply_filters('wp_optimize_admin_page_'.$page.'_tabs', $tabs);
91 if (!empty($filtered_tabs) && is_array($filtered_tabs)) return $filtered_tabs;
92 return $tabs;
93 }
94
95 /**
96 * Main page structure.
97 */
98 public function display_admin() {
99 $capability_required = WP_Optimize()->capability_required();
100 $can_run_optimizations = WP_Optimize()->can_run_optimizations();
101 $can_manage_options = WP_Optimize()->can_manage_options();
102
103 if (!current_user_can($capability_required) || (!$can_run_optimizations && !$can_manage_options)) {
104 echo esc_html__('Permission denied.', 'wp-optimize');
105 return;
106 }
107
108 $this->register_admin_content();
109
110 global $wp_version;
111
112 echo '<div id="wp-optimize-wrap" class="'.(version_compare($wp_version, '7.0', '>=') ? 'wp-version-7' : '').'">';
113
114 WP_Optimize()->include_template('admin-page-header.php', false, array('show_notices' => !(WP_Optimize()->get_install_or_update_notice()->show_current_notice())));
115
116 do_action('wpo_admin_after_header');
117
118 echo '<div id="actions-results-area"></div>';
119
120 $pages = $this->get_submenu_items();
121
122 foreach ($pages as $page) {
123 if (isset($page['menu_slug'])) {
124 $this->display_admin_page($page['menu_slug']);
125 }
126 }
127
128 do_action('wpo_admin_before_closing_wrap');
129
130 // closes main plugin wrapper div. #wp-optimize-wrap
131 echo '</div><!-- END #wp-optimize-wrap -->';
132
133 }
134
135 /**
136 * Prepare and display admin page with $page id.
137 *
138 * @param string $page wp-optimize page id i.e. dashboard, database, images, cache, ...
139 */
140 public function display_admin_page($page) {
141 $active_page = TeamUpdraft\WP_Optimize\Includes\Fragments\fetch_superglobal('request', 'page', 'string', 'sanitize_text_field', '');
142
143 echo '<div class="wpo-page' . ($active_page === $page ? ' active' : '') . '" data-whichpage="'.esc_attr($page).'">';
144
145 echo '<div class="wpo-main">';
146
147 // get defined tabs for $page.
148 $tabs = $this->get_tabs($page);
149
150 // if no tabs defined for $page then use $page as $active_tab for load template, doing related actions e t.c.
151 if (empty($tabs)) {
152 $active_tab = $page;
153 } else {
154 $tab_keys = array_keys($tabs);
155 $default_tab = apply_filters('wp_optimize_admin_'.$page.'_default_tab', $tab_keys[0]);
156 $active_tab = substr(TeamUpdraft\WP_Optimize\Includes\Fragments\fetch_superglobal('get', 'tab', null, 'sanitize_text_field', $default_tab), 12);
157 if (!in_array($active_tab, array_keys($tabs))) $active_tab = $default_tab;
158 }
159
160 do_action('wp_optimize_admin_page_'.$page, $active_tab);
161
162 // if tabs defined then display
163 if (!empty($tabs)) {
164 WP_Optimize()->include_template('admin-page-header-tabs.php', false, array('page' => $page, 'active_tab' => $active_tab, 'tabs' => $tabs, 'wpo_is_premium' => WP_Optimize::is_premium()));
165 }
166
167 foreach ($tabs as $tab_id => $tab_description) {
168 // output wrap div for tab with id #wp-optimize-nav-tab-contents-'.$page.'-'.$tab_id
169 echo '<div class="wp-optimize-nav-tab-contents" id="wp-optimize-nav-tab-'.esc_attr($page).'-'.esc_attr($tab_id).'-contents" '.(($tab_id === $active_tab) ? '' : 'style="display:none;"').'>';
170
171 echo '<div class="postbox wpo-tab-postbox">';
172 // call action for generate tab content.
173
174 do_action('wp_optimize_admin_page_'.$page.'_'.$tab_id);
175
176 // closes postbox.
177 echo '</div><!-- END .postbox -->';
178 // closes tab wrapper.
179 echo '</div><!-- END .wp-optimize-nav-tab-contents -->';
180 }
181
182 echo '</div><!-- END .wpo-main -->';
183
184 do_action('wp_optimize_admin_after_page_'.$page, $active_tab);
185
186 echo '</div><!-- END .wpo-page -->';
187
188 }
189
190 /**
191 * Define required actions for admin pages.
192 */
193 public function register_admin_content() {
194
195 do_action('wp_optimize_register_admin_content');
196
197 /**
198 * SETTINGS
199 */
200 add_action('wp_optimize_admin_page_wpo_settings_settings', array($this, 'output_dashboard_settings_tab'), 20);
201 add_action('wp_optimize_admin_page_wpo_settings_status', array($this, 'output_dashboard_status_tab'));
202
203 /**
204 * UpdraftCentral
205 */
206 // add_action('wp_optimize_admin_page_wpo_settings_updraftcentral', array($this, 'output_dashboard_updraftcentral_tab'), 20);
207
208 /**
209 * Premium / other plugins
210 */
211 add_action('wp_optimize_admin_page_wpo_mayalso_may_also', array($this, 'output_dashboard_other_plugins_tab'), 20);
212
213 /**
214 * DATABASE
215 */
216 add_action('wp_optimize_admin_page_WP-Optimize_optimize', array($this, 'output_database_optimize_tab'), 20);
217 add_action('wp_optimize_admin_page_WP-Optimize_tables', array($this, 'output_database_tables_tab'), 20);
218 add_action('wp_optimize_admin_page_WP-Optimize_settings', array($this, 'output_database_settings_tab'), 20);
219 add_action('wp_optimize_admin_page_WP-Optimize_table_analysis', array($this, 'output_table_usage_tab'), 20);
220 /**
221 * PERFORMANCE
222 */
223 add_action('wp_optimize_admin_page_wpo_performance_404_detector', array($this, 'output_performance_404_requests'), 20);
224
225 /**
226 * CACHE
227 */
228 add_action('wp_optimize_admin_page_wpo_cache_cache', array($this, 'output_page_cache_tab'), 20);
229 if (!WP_Optimize()->get_server_compatibility_instance()->does_server_handle_cache()) {
230 add_action('wp_optimize_admin_page_wpo_cache_preload', array($this, 'output_page_cache_preload_tab'), 20);
231 add_action('wp_optimize_admin_page_wpo_cache_advanced', array($this, 'output_page_cache_advanced_tab'), 20);
232 }
233 add_action('wp_optimize_admin_page_wpo_cache_gzip', array($this, 'output_cache_gzip_tab'), 20);
234 add_action('wp_optimize_admin_page_wpo_cache_settings', array($this, 'output_cache_settings_tab'), 20);
235 add_action('wpo_page_cache_advanced_settings', array($this, 'output_cloudflare_settings'), 20);
236 add_action('wp_optimize_admin_page_wpo_cache_lcp', array($this, 'output_page_cache_lcp'), 20);
237
238 /**
239 * SUPPORT
240 */
241 add_action('wp_optimize_admin_page_wpo_support_support', array($this, 'output_dashboard_support_tab'), 20);
242 // Display Support page.
243
244 if (!WP_Optimize::is_premium()) {
245 /**
246 * Add action for display Images > Unused images and sizes tab.
247 */
248 add_action('wp_optimize_admin_page_wpo_images_unused', array($this, 'admin_page_wpo_images_unused'));
249
250 /**
251 * Add action for display Dashboard > Lazyload tab.
252 */
253 add_action('wp_optimize_admin_page_wpo_images_lazyload', array($this, 'admin_page_wpo_images_lazyload'));
254 } else {
255 /**
256 * Add filter for display footer review message and link.
257 */
258 add_filter('admin_footer_text', array($this, 'display_footer_review_message'));
259 }
260
261 /**
262 * Add action for display Images > Images dimensions tab.
263 */
264 add_action('wp_optimize_admin_page_wpo_images_dimensions', array($this, 'admin_page_wpo_images_dimensions'));
265 }
266
267 /**
268 * Database settings
269 */
270 public function output_database_settings_tab() {
271
272 if (WP_Optimize()->can_run_optimizations()) {
273 $wp_optimize_commands = new WP_Optimize_Commands();
274 $settings_general_data = $wp_optimize_commands->get_widgets_data(array('widgets' => array('wp_optimize_general_settings')));
275 $settings_cleanup_data = $wp_optimize_commands->get_widgets_data(array('widgets' => array('wp_optimize_schedule_cleanup_settings')));
276
277 WP_Optimize()->include_template('database/settings.php', false, array('settings_general_data' => $settings_general_data['data']['wp_optimize_general_settings'], 'settings_cleanup_data' => $settings_cleanup_data['data']['wp_optimize_schedule_cleanup_settings']));
278 } else {
279 $this->prevent_manage_options_info();
280 }
281 }
282
283 /**
284 * Table usage tab
285 *
286 * @return void
287 */
288 public function output_table_usage_tab() {
289 if (WP_Optimize::is_premium()) {
290 $extract = array('is_enabled' => (bool) WP_Optimize()->get_options()->get_option(WPO_DB_Table_Analysis::ENABLED_SETTING_NAME), 'dashboard' => WP_Optimize_Premium()->get_db_table_analysis_dashboard());
291 } else {
292 $extract = array('is_enabled' => false);
293 }
294 WP_Optimize()->include_template('database/table-analysis.php', false, $extract);
295 }
296
297 /**
298 * Dashboard settings
299 */
300 public function output_dashboard_settings_tab() {
301 if (isset($_SERVER['REQUEST_METHOD']) && 'POST' === $_SERVER['REQUEST_METHOD']) {
302 // Nonce check.
303 check_admin_referer('wpo_settings');
304
305 if (isset($_POST['wp-optimize-settings'])) {
306 $options = WP_Optimize()->get_options();
307 // save settings request sent.
308 $output = $options->save_settings($_POST);
309
310 $this->wpo_render_output_messages($output);
311 }
312 }
313
314 if (WP_Optimize()->can_manage_options()) {
315 $wp_optimize_commands = new WP_Optimize_Commands();
316 $loggers_data = $wp_optimize_commands->get_widgets_data(array('widgets' => array('wp_optimize_logging_settings')));
317 $settings_trackback_data = $wp_optimize_commands->get_widgets_data(array('widgets' => array('wp_optimize_trackback_toggle_settings')));
318 $settings_comments_data = $wp_optimize_commands->get_widgets_data(array('widgets' => array('wp_optimize_comments_toggle_settings')));
319 $settings_general_data = $wp_optimize_commands->get_widgets_data(array('widgets' => array('wp_optimize_general_settings')));
320
321 WP_Optimize()->include_template('settings/settings.php', false, array('loggers_data' => $loggers_data['data']['wp_optimize_logging_settings'], 'settings_trackback_data' => $settings_trackback_data['data']['wp_optimize_trackback_toggle_settings'], 'settings_comments_data' => $settings_comments_data['data']['wp_optimize_comments_toggle_settings'], 'settings_general_data' => $settings_general_data['data']['wp_optimize_general_settings']));
322 } else {
323 $this->prevent_manage_options_info();
324 }
325 }
326
327 /**
328 * Outputs the system status page
329 */
330 public function output_dashboard_status_tab() {
331 WP_Optimize()->include_template('status/status-page.php');
332 }
333
334 /**
335 * UpdraftCentral settings tab
336 */
337 public function output_dashboard_updraftcentral_tab() {
338 if (WP_Optimize()->can_manage_options()) {
339 global $updraftcentral_host_plugin;
340 $updraftcentral_host_plugin->debugtools_dashboard();
341 } else {
342 $this->prevent_manage_options_info();
343 }
344 }
345
346 /**
347 * Dashboard support tab
348 */
349 public function output_dashboard_support_tab() {
350 WP_Optimize()->include_template('settings/support-and-faqs.php');
351 }
352
353 /**
354 * Dashboard Other plugins / premium tab
355 */
356 public function output_dashboard_other_plugins_tab() {
357 WP_Optimize()->include_template('settings/may-also-like.php');
358 }
359
360 /**
361 * Cache tab
362 */
363 public function output_page_cache_tab() {
364 $wpo_cache = WP_Optimize()->get_page_cache();
365 $wpo_cache_options = $wpo_cache->config->get();
366 $display = $wpo_cache->is_enabled() ? "display: block;" : "display: none;";
367 $error = is_wp_error(WP_Optimize()->get_init_page_cache_status()) ? WP_Optimize()->get_init_page_cache_status()->get_error_message() : '';
368
369 WP_Optimize()->include_template('cache/page-cache.php', false, array(
370 'wpo_cache' => $wpo_cache,
371 'active_cache_plugins' => WP_Optimize_Detect_Cache_Plugins::instance()->get_active_cache_plugins(),
372 'wpo_cache_options' => $wpo_cache_options,
373 'cache_size' => $wpo_cache->get_cache_size(),
374 'display' => $display,
375 'can_purge_the_cache' => $wpo_cache->can_purge_cache(),
376 'auto_preload_purged_contents' => $wpo_cache_options['auto_preload_purged_contents'],
377 'does_server_handle_cache' => WP_Optimize()->get_server_compatibility_instance()->does_server_handle_cache(),
378 'error' => $error,
379 ));
380 }
381
382 /**
383 * Preload tab
384 */
385 public function output_page_cache_preload_tab() {
386 $wpo_cache = WP_Optimize()->get_page_cache();
387 $wpo_cache_options = $wpo_cache->config->get();
388 $wpo_cache_preloader = WP_Optimize_Page_Cache_Preloader::instance();
389 $is_running = $wpo_cache_preloader->is_busy() && !$wpo_cache_preloader->is_cancelled();
390 $status = $wpo_cache_preloader->get_status_info();
391
392 $scheduled_types = WP_Optimize::get_schedule_types();
393 $scheduled_types = array_filter($scheduled_types, function($type) {
394 return 'wpo_once' !== $type;
395 }, ARRAY_FILTER_USE_KEY);
396 $schedule_options = array_merge(
397 array(
398 'wpo_use_cache_lifespan' => __('Same as cache lifespan', 'wp-optimize')
399 ),
400 $scheduled_types
401 );
402
403 WP_Optimize()->include_template('cache/page-cache-preload.php', false, array(
404 'wpo_cache_options' => $wpo_cache_options,
405 'is_running' => $is_running,
406 'status_message' => $status['message'] ?? '',
407 'schedule_options' => $schedule_options
408 ));
409 }
410
411 /**
412 * Advanced tab
413 */
414 public function output_page_cache_advanced_tab() {
415 $wpo_cache = WP_Optimize()->get_page_cache();
416 $wpo_cache_options = $wpo_cache->config->get();
417
418 $cache_exception_conditional_tags = is_array($wpo_cache_options['cache_exception_conditional_tags']) ? join("\n", $wpo_cache_options['cache_exception_conditional_tags']) : '';
419 $cache_include_urls = is_array($wpo_cache_options['cache_include_urls']) ? join("\n", $wpo_cache_options['cache_include_urls']) : '';
420 $cache_exception_urls = is_array($wpo_cache_options['cache_exception_urls']) ? join("\n", $wpo_cache_options['cache_exception_urls']) : '';
421 $cache_ignore_query_variables = is_array($wpo_cache_options['cache_ignore_query_variables']) ? join("\n", $wpo_cache_options['cache_ignore_query_variables']) : '';
422 $cache_exception_cookies = is_array($wpo_cache_options['cache_exception_cookies']) ? join("\n", $wpo_cache_options['cache_exception_cookies']) : '';
423 $cache_exception_browser_agents = is_array($wpo_cache_options['cache_exception_browser_agents']) ? join("\n", $wpo_cache_options['cache_exception_browser_agents']) : '';
424
425 WP_Optimize()->include_template('cache/page-cache-advanced.php', false, array(
426 'wpo_cache' => $wpo_cache,
427 'wpo_cache_options' => $wpo_cache_options,
428 'show_avatars' => (bool) get_option('show_avatars'),
429 'cache_include_urls' => $cache_include_urls,
430 'cache_exception_urls' => $cache_exception_urls,
431 'cache_ignore_query_variables' => $cache_ignore_query_variables,
432 'cache_exception_conditional_tags' => $cache_exception_conditional_tags,
433 'cache_exception_cookies' => $cache_exception_cookies,
434 'cache_exception_browser_agents' => $cache_exception_browser_agents,
435 ));
436 }
437
438 /**
439 * Gzip tab
440 */
441 public function output_cache_gzip_tab() {
442 $wpo_gzip_compression = WP_Optimize()->get_gzip_compression();
443 $wpo_gzip_compression_enabled = $wpo_gzip_compression->is_gzip_compression_enabled(true);
444 $wpo_gzip_headers_information = $wpo_gzip_compression->get_headers_information();
445 $is_cloudflare_site = $this->is_cloudflare_site();
446 $is_gzip_compression_section_exists = $wpo_gzip_compression->is_gzip_compression_section_exists();
447 $wpo_gzip_compression_enabled_by_wpo = $is_gzip_compression_section_exists && $wpo_gzip_compression_enabled && !$is_cloudflare_site && !(is_array($wpo_gzip_headers_information) && 'brotli' === $wpo_gzip_headers_information['compression']);
448
449 WP_Optimize()->include_template('cache/gzip-compression.php', false, array(
450 'wpo_gzip_headers_information' => $wpo_gzip_headers_information,
451 'wpo_gzip_compression_enabled' => $wpo_gzip_compression_enabled,
452 'is_cloudflare_site' => $is_cloudflare_site,
453 'wpo_gzip_compression_enabled_by_wpo' => $wpo_gzip_compression_enabled_by_wpo,
454 'wpo_gzip_compression_settings_added' => $is_gzip_compression_section_exists,
455 'info_link' => 'https://teamupdraft.com/documentation/wp-optimize/topics/caching/faqs/what-is-gzip-compression/?utm_source=wpo-plugin&utm_medium=referral&utm_campaign=paac&utm_content=lossy-compression-guide&utm_creative_format=text',
456 'faq_link' => 'https://getwpo.com/gzip-faq-link/',
457 'class_name' => (!is_wp_error($wpo_gzip_compression_enabled) && $wpo_gzip_compression_enabled ? 'wpo-enabled' : 'wpo-disabled')
458 ));
459 }
460
461 /**
462 * Cache tab
463 */
464 public function output_cache_settings_tab() {
465
466 $wpo_browser_cache = WP_Optimize()->get_browser_cache();
467 $wpo_browser_cache_enabled = $wpo_browser_cache->is_enabled();
468
469 WP_Optimize()->include_template('cache/browser-cache.php', false, array(
470 'wpo_browser_cache_enabled' => $wpo_browser_cache_enabled,
471 'is_cloudflare_handling_browser_cache' => $this->is_cloudflare_handling_browser_cache(),
472 'wpo_browser_cache_settings_added' => $wpo_browser_cache->is_browser_cache_section_exists(),
473 'class_name' => (true === $wpo_browser_cache_enabled ? 'wpo-enabled' : 'wpo-disabled'),
474 'wpo_browser_cache_expire_days' => WP_Optimize()->get_options()->get_option('browser_cache_expire_days', '28'),
475 'wpo_browser_cache_expire_hours' => WP_Optimize()->get_options()->get_option('browser_cache_expire_hours', '0'),
476 'info_link' => 'https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching',
477 'faq_link' => 'https://www.digitalocean.com/community/tutorials/how-to-implement-browser-caching-with-nginx-s-header-module-on-ubuntu-16-04',
478 ));
479 }
480
481 /**
482 * Cache: Auto LCP tab
483 */
484 public function output_page_cache_lcp() {
485 $lcp_options = array();
486 if (WP_Optimize::is_premium()) {
487 $lcp_options['lcp_preload_enable'] = (bool) WPO_Cache_Config::instance()->get_option('lcp_preload_enable');
488 }
489 WP_Optimize()->include_template('cache/page-cache-lcp-settings.php', false, $lcp_options);
490 }
491
492 /**
493 * Check if is the current site handled with Cloudflare.
494 *
495 * @return bool
496 */
497 public function is_cloudflare_site(): bool {
498 $response = wp_remote_get(home_url());
499 if (is_wp_error($response)) return false;
500
501 $cloudflare_status = wp_remote_retrieve_header($response, 'cf-cache-status');
502
503 return !empty($cloudflare_status);
504 }
505
506 /**
507 * Check if browser cache rules is handled by Cloudflare.
508 *
509 * @return bool
510 */
511 private function is_cloudflare_handling_browser_cache(): bool {
512 $response = wp_remote_get(home_url());
513 if (is_wp_error($response)) return false;
514
515 $headers = wp_remote_retrieve_headers($response);
516 return isset($headers['cf-cache-status']) && (isset($headers['cache-control']) || isset($headers['expires']));
517 }
518
519 /**
520 * Include Cloudflare settings template.
521 */
522 public function output_cloudflare_settings() {
523 if (WP_Optimize::is_premium() || !apply_filters('show_cloudflare_settings', $this->is_cloudflare_site())) return;
524
525 WP_Optimize()->include_template('cache/page-cache-cloudflare-placeholder.php');
526 }
527
528 /**
529 * Outputs the DB optimize Tab
530 */
531 public function output_database_optimize_tab() {
532 $optimizer = WP_Optimize()->get_optimizer();
533 $options = WP_Optimize()->get_options();
534 $optimization_results = false;
535
536 $nonce_passed = TeamUpdraft\WP_Optimize\Includes\Fragments\verify_nonce('_wpnonce', 'wpo_optimization');
537
538 // save options.
539 $post = TeamUpdraft\WP_Optimize\Includes\Fragments\fetch_superglobal('post', 'wp-optimize');
540
541 if ($nonce_passed && $post) $options->save_sent_manual_run_optimization_options($_POST, true); // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Only isset is used to check
542
543 $optimize_db = $nonce_passed && TeamUpdraft\WP_Optimize\Includes\Fragments\fetch_superglobal('post', 'optimize-db');
544
545 $optimization_results = (($nonce_passed) ? $optimizer->do_optimizations($_POST) : false); // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Only isset is used to check, and compared again literal string
546
547 // display optimizations table or restricted access message.
548 if (WP_Optimize()->can_run_optimizations()) {
549 $wp_optimize_commands = new WP_Optimize_Commands();
550 $status_data = $wp_optimize_commands->get_widgets_data(array('widgets' => array('all_status')));
551 $optimizations_table_data = $wp_optimize_commands->get_widgets_data(array('widgets' => array('wp_optimize')));
552 WP_Optimize()->include_template('database/optimize-table.php', false, array(
553 'optimize_db' => $optimize_db,
554 'optimization_results' => $optimization_results,
555 'load_data' => false,
556 'does_server_allow_table_optimization' => WP_Optimize()->get_server_compatibility_instance()->does_server_allow_table_optimization(),
557 'optimizations_table_data' => $optimizations_table_data['data']['wp_optimize'],
558 'status_data' => $status_data['data']['all_status']
559 ));
560 } else {
561 $this->prevent_run_optimizations_message();
562 }
563 }
564
565 /**
566 * Outputs the DB Tables Tab
567 */
568 public function output_database_tables_tab() {
569 $nonce_passed = TeamUpdraft\WP_Optimize\Includes\Fragments\verify_nonce('_wpnonce', 'wpo_optimization');
570
571 $optimize_db = $nonce_passed && TeamUpdraft\WP_Optimize\Includes\Fragments\fetch_superglobal('post', 'optimize-db');
572
573 if (!WP_Optimize()->get_server_compatibility_instance()->does_server_allow_table_optimization()) {
574 $message = __('Your server takes care of table optimization', 'wp-optimize');
575 $this->prevent_run_optimizations_message($message);
576 } elseif (WP_Optimize()->can_run_optimizations()) {
577 WP_Optimize()->include_template('database/tables.php', false, array('optimize_db' => $optimize_db, 'load_data' => WP_Optimize()->template_should_include_data()));
578 } else {
579 $this->prevent_run_optimizations_message();
580 }
581 }
582
583 /**
584 * Outputs Performance 404 requests Tab
585 */
586 public function output_performance_404_requests() {
587 $wp_optimize = WP_Optimize();
588 $is_enabled = $wp_optimize->get_options()->get_option('404_detector', 0);
589
590 $detector = $wp_optimize->get_404_detector();
591 $suspicious_threshold = $detector->get_suspicious_request_count_threshold();
592
593 $report_has_data = false;
594 $requests = array();
595
596 if ($is_enabled) {
597 $requests = $detector->get_suspicious_requests();
598
599 foreach ($requests as $url_requests) {
600 foreach ($url_requests as $row) {
601 if (1 < $row->occurrences && 'grouped' === $row->row_type) {
602 if (0 === $row->non_suspicious_referrers && 1 < $row->total_referrers) {
603 continue;
604 }
605 }
606 $report_has_data = true;
607 }
608 }
609 }
610
611 $wp_optimize->include_template('performance/404-detector.php', false, array(
612 'requests' => $requests,
613 'suspicious_threshold' => $suspicious_threshold,
614 'obj_404_detector' => $detector,
615 'report_has_data' => $report_has_data,
616 'is_enabled' => $is_enabled,
617 ));
618 }
619
620 /**
621 * Runs upon the WP action admin_page_wpo_images_unused
622 */
623 public function admin_page_wpo_images_unused() {
624 WP_Optimize()->include_template('images/unused.php');
625 }
626
627 /**
628 * Runs upon the WP action wp_optimize_admin_page_wpo_images_lazyload
629 */
630 public function admin_page_wpo_images_lazyload() {
631 WP_Optimize()->include_template('images/lazyload.php');
632 }
633
634 /**
635 * Runs upon the WP action wp_optimize_admin_page_wpo_images_dimensions
636 */
637 public function admin_page_wpo_images_dimensions() {
638 $options = WP_Optimize()->get_options();
639 $image_dimensions = $options->get_option('image_dimensions');
640 $ignore_classes = $options->get_option('image_dimensions_ignore_classes');
641 WP_Optimize()->include_template('images/dimensions.php', false, array(
642 'images_dimensions_status' => $image_dimensions,
643 'ignore_classes' => $ignore_classes ?: '',
644 ));
645 }
646
647 /**
648 * Show footer review message and link.
649 *
650 * @return string
651 */
652 public function display_footer_review_message() {
653 $message = sprintf(
654 // translators: %1$s is plugin name, %2$s is 5-star rating, %3$s is link to Trustpilot, %4$s is link to G2.
655 __('Enjoyed %1$s? Please leave us a %2$s rating on %3$s or %4$s.', 'wp-optimize').' '.__('We really appreciate your support!', 'wp-optimize'),
656 '<b>WP-Optimize</b>',
657 '<span style="color:#2271b1">&starf;&starf;&starf;&starf;&starf;</span>',
658 '<a href="https://uk.trustpilot.com/review/getwpo.com" target="_blank">Trustpilot</a>',
659 '<a href="https://www.g2.com/products/wp-optimize/reviews" target="_blank">G2.com</a>'
660 );
661 return $message;
662 }
663
664 /**
665 * Adds menu in admin bar
666 */
667 public function wpo_admin_bar() {
668 $wp_admin_bar = $GLOBALS['wp_admin_bar'];
669
670 if (defined('WPOPTIMIZE_ADMINBAR_DISABLE') && WPOPTIMIZE_ADMINBAR_DISABLE) return;
671
672 // Show menu item in top bar only for super admins.
673 if (is_multisite() & !is_super_admin(get_current_user_id())) return;
674
675 // Add a link called at the top admin bar.
676 $args = array(
677 'id' => 'wp-optimize-node',
678 'title' => apply_filters('wpoptimize_admin_node_title', 'WP-Optimize')
679 );
680 $wp_admin_bar->add_node($args);
681
682 $pages = $this->get_submenu_items();
683
684 foreach ($pages as $page_id => $page) {
685
686 if (!isset($page['create_submenu']) || !$page['create_submenu']) {
687 if (isset($page['icon']) && 'separator' === $page['icon']) {
688 $args = array(
689 'id' => 'wpo-separator-'.$page_id,
690 'parent' => 'wp-optimize-node',
691 'meta' => array(
692 'class' => 'separator',
693 ),
694 );
695 $wp_admin_bar->add_node($args);
696 }
697 continue;
698 }
699
700 // 'menu_slug' => 'WP-Optimize',
701
702 $menu_page_url = menu_page_url($page['menu_slug'], false);
703
704 if (is_multisite()) {
705 $menu_page_url = network_admin_url('admin.php?page='.$page['menu_slug']);
706 }
707
708 $args = array(
709 'id' => 'wpoptimize_admin_node_'.$page_id,
710 'title' => $page['menu_title'],
711 'parent' => 'wp-optimize-node',
712 'href' => $menu_page_url,
713 );
714 $wp_admin_bar->add_node($args);
715 }
716
717 }
718
719 /**
720 * Manages the admin bar menu for caching (currently page and minify)
721 */
722 public function cache_admin_bar($wp_admin_bar) {
723 $options = WP_Optimize()->get_options();
724 if (!$options->get_option('enable_cache_in_admin_bar', true)) return;
725
726 /**
727 * The "purge cache" menu items
728 *
729 * @param array $menu_items - The menu items, in the format required by $wp_admin_bar->add_menu()
730 * @param object $wp_admin_bar
731 */
732 $menu_items = apply_filters('wpo_cache_admin_bar_menu_items', array(), $wp_admin_bar);
733
734 if (empty($menu_items) || !is_array($menu_items)) return;
735
736 $wp_admin_bar->add_menu(array(
737 'id' => 'wpo_purge_cache',
738 'title' => __('Purge cache', 'wp-optimize'),
739 'href' => '#',
740 'meta' => array(
741 'title' => __('Purge cache', 'wp-optimize'),
742 ),
743 'parent' => false,
744 ));
745
746 foreach ($menu_items as $item) {
747 $wp_admin_bar->add_menu($item);
748 }
749 }
750
751 /**
752 * Adds and displays menu and submenu pages
753 */
754 public function admin_menu() {
755
756 $capability_required = WP_Optimize()->capability_required();
757 $can_run_optimizations = WP_Optimize()->can_run_optimizations();
758 $can_manage_options = WP_Optimize()->can_manage_options();
759
760 if (!WP_Optimize()->current_user_can() || (!$can_run_optimizations && !$can_manage_options)) return;
761
762 $icon_svg = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgdmlld0JveD0iMCAwIDE2IDE2IgogICB2ZXJzaW9uPSIxLjEiCiAgIGlkPSJzdmc0MzE2IgogICBoZWlnaHQ9IjE2IgogICB3aWR0aD0iMTYiPgogIDxkZWZzCiAgICAgaWQ9ImRlZnM0MzE4IiAvPgogIDxtZXRhZGF0YQogICAgIGlkPSJtZXRhZGF0YTQzMjEiPgogICAgPHJkZjpSREY+CiAgICAgIDxjYzpXb3JrCiAgICAgICAgIHJkZjphYm91dD0iIj4KICAgICAgICA8ZGM6Zm9ybWF0PmltYWdlL3N2Zyt4bWw8L2RjOmZvcm1hdD4KICAgICAgICA8ZGM6dHlwZQogICAgICAgICAgIHJkZjpyZXNvdXJjZT0iaHR0cDovL3B1cmwub3JnL2RjL2RjbWl0eXBlL1N0aWxsSW1hZ2UiIC8+CiAgICAgICAgPGRjOnRpdGxlPjwvZGM6dGl0bGU+CiAgICAgIDwvY2M6V29yaz4KICAgIDwvcmRmOlJERj4KICA8L21ldGFkYXRhPgogIDxnCiAgICAgaWQ9ImxheWVyMSI+CiAgICA8cGF0aAogICAgICAgc3R5bGU9ImZpbGw6I2EwYTVhYTtmaWxsLW9wYWNpdHk6MSIKICAgICAgIGlkPSJwYXRoNTciCiAgICAgICBkPSJtIDEwLjc2ODgwOSw2Ljc2MTYwNTEgMCwwIGMgLTAuMDE2ODgsLTAuMDE2ODc4IC0wLjAyNTMxLC0wLjA0MjE4MSAtMC4wMzM3NCwtMC4wNjc0OTkgLTAuMDA4NCwtMC4wMDgzOSAtMC4wMDg0LC0wLjAxNjg3OCAtMC4wMTY4OCwtMC4wMzM3NDMgQyA5Ljk5MjYxMTIsNS4xOTIzMzY2IDguMjIwODU1Nyw0LjU4NDg3ODEgNi43NDQzOTEyLDUuMjkzNTc5NyA1LjY3MjkwMDUsNS44MDgyMzI4IDUuMDU3MDA0Myw2Ljg4ODE2MTMgNS4wNjU0NDIsOC4wMDE4MzY1IDQuNDU3OTgyMiw3LjMxMDAwNzYgMy42OTg2NTg0LDYuNzk1MzU0NSAyLjg1NDk2NDIsNi40OTE2MjUzIDMuMjY4Mzc0Myw1LjA2NTc4MzEgNC4yNTU0OTYsMy44MTcxMTY2IDUuNjg5Nzc0NiwzLjEyNTI4NzggOC4zNjQyODMyLDEuODM0NDM2OCAxMS41NzAzMTksMi45Mzk2NzQ0IDEyLjg4NjQ4MSw1LjU4ODg3MjYgMTMuNDUxNzU1LDYuNzI3ODU5NiAxNC42NDk4MDEsNy4zNTIxOTIxIDE1Ljg0Nzg0Niw3LjIzNDA3NSAxNS43NjM0ODIsNi4zMzk3NiAxNS41MTg4MDUsNS40MzcwMDg2IDE1LjEwNTM5Niw0LjU3NjQ0MDQgMTMuMjE1NTIxLDAuNjg3MDEzNCA4LjUzMzAyMjYsLTAuOTQxMzE2MjcgNC42NDM1OTQzLDAuOTQwMTIxNzkgMi4zMjM0MzcsMi4wNjIyMzM0IDAuODA0Nzg4MTQsNC4xNzk5MDQ0IDAuMzU3NjMxMzIsNi41MzM4MDk4IDIuNDE2MjQzOCw2LjQyNDEyOSA0LjQzMjY3MTcsNy41MDQwNTc0IDUuNDM2NjY2Miw5LjQzNjExNjcgbCAwLjAwODM5LDAgYyAwLjc1OTMxOTIsMS4zNzUyMjAzIDIuNDcyMDE3OCwxLjk0MDQ5NTMgMy45MDYyOTYsMS4yNDg2NjczIDEuMDQ2MTc5OCwtMC41MDYyMTggMS42NTM2NDA4LC0xLjUzNTUyMzggMS42Nzg5NTA4LC0yLjYxNTQ1MTIgMC41ODIxNDgsMC43MDg3MDE4IDEuMzMzMDM1LDEuMjQ4NjY2OCAyLjE1OTg1NiwxLjU3NzcwNjQgLTAuNDM4NzIxLDEuMzU4MzQ3OCAtMS40MDA1MzMsMi41NDc5NTQ4IC0yLjc5MjYyNywzLjIxNDQ3ODggLTIuNTkwMTM4NywxLjI0ODY1OCAtNS42NzgwNTc0LDAuMjUzMTA0IC03LjA2MTcxNTEsLTIuMjI3MzU3IGwgMCwwIEMgMi43NjIxMDQ4LDkuNDUyOTg5NCAxLjUxMzQzODMsOC44MjAyMTkxIDAuMjgxNjQ1OTIsOC45NzIwODQ0IDAuMzgyODg3NjUsOS43OTg5MDQ2IDAuNjE5MTIzMzEsMTAuNjE3Mjg3IDAuOTk4Nzg1MiwxMS40MDE5MjIgYyAxLjg4MTQzNjgsMy44OTc4NjQgNi41NjM5MzcsNS41MjYxOTggMTAuNDYxODAwOCwzLjY0NDc2IDIuMjQ0MjI2LC0xLjA4ODM2OSAzLjczNzU2MiwtMy4xMDQ3OTYgNC4yMzUzNDIsLTUuMzc0MzMyMyAtMS45OTk1NTQsMC4wNDIxODEgLTMuOTQ4NDg2LC0xLjAyOTMwNjMgLTQuOTI3MTcsLTIuOTEwNzQzMyB6IgogICAgICAgY2xhc3M9InN0MTciIC8+CiAgPC9nPgo8L3N2Zz4K';
763
764 // Removes the admin menu items on the left WP bar.
765 if (!is_multisite() || (is_multisite() && is_network_admin())) {
766 add_menu_page("WP-Optimize", "WP-Optimize", $capability_required, "WP-Optimize", array($this, "display_admin"), $icon_svg);
767
768 $sub_menu_items = $this->get_submenu_items();
769
770 foreach ($sub_menu_items as $menu_item) {
771 if ($menu_item['create_submenu']) add_submenu_page('WP-Optimize', $menu_item['page_title'], $menu_item['menu_title'], $capability_required, $menu_item['menu_slug'], $menu_item['function']);
772 }
773 }
774
775 $options = WP_Optimize()->get_options();
776
777 if ('true' === $options->get_option('enable-admin-menu', 'false')) {
778 add_action('wp_before_admin_bar_render', array($this, 'wpo_admin_bar'));
779 }
780 }
781
782 /**
783 * Get the submenu items
784 *
785 * @return array
786 */
787 public function get_submenu_items() {
788 $sub_menu_items = array(
789 array(
790 'page_title' => __('Database', 'wp-optimize'),
791 'menu_title' => __('Database', 'wp-optimize'),
792 'menu_slug' => 'WP-Optimize',
793 'function' => array($this, 'display_admin'),
794 'icon' => 'cloud',
795 'create_submenu' => true,
796 'order' => 20,
797 ),
798 array(
799 'page_title' => __('Images', 'wp-optimize'),
800 'menu_title' => __('Images', 'wp-optimize'),
801 'menu_slug' => 'wpo_images',
802 'function' => array($this, 'display_admin'),
803 'icon' => 'images-alt2',
804 'create_submenu' => true,
805 'order' => 30,
806 ),
807 array(
808 'page_title' => __('Cache', 'wp-optimize'),
809 'menu_title' => __('Cache', 'wp-optimize'),
810 'menu_slug' => 'wpo_cache',
811 'function' => array($this, 'display_admin'),
812 'icon' => 'archive',
813 'create_submenu' => true,
814 'order' => 40,
815 ),
816 array(
817 'page_title' => __('Minify', 'wp-optimize'),
818 'menu_title' => __('Minify', 'wp-optimize'),
819 'menu_slug' => 'wpo_minify',
820 'function' => array($this, 'display_admin'),
821 'icon' => 'editor-contract',
822 'create_submenu' => true,
823 'order' => 50,
824 ),
825 array(
826 'page_title' => __('Performance', 'wp-optimize'),
827 'menu_title' => __('Performance', 'wp-optimize'),
828 'menu_slug' => 'wpo_performance',
829 'function' => array($this, 'display_admin'),
830 'icon' => 'performance',
831 'create_submenu' => true,
832 'order' => 53,
833 ),
834 array(
835 'create_submenu' => false,
836 'order' => 55,
837 'icon' => 'separator',
838 ),
839 array(
840 'page_title' => __('Settings', 'wp-optimize'),
841 'menu_title' => __('Settings', 'wp-optimize'),
842 'menu_slug' => 'wpo_settings',
843 'function' => array($this, 'display_admin'),
844 'icon' => 'admin-settings',
845 'create_submenu' => true,
846 'order' => 60,
847 ),
848 array(
849 'page_title' => __('Support & FAQs', 'wp-optimize'),
850 'menu_title' => __('Help', 'wp-optimize'),
851 'menu_slug' => 'wpo_support',
852 'function' => array($this, 'display_admin'),
853 'icon' => 'sos',
854 'create_submenu' => true,
855 'order' => 60,
856 ),
857 array(
858 'page_title' => __('Premium Upgrade', 'wp-optimize'),
859 'menu_title' => __('Premium Upgrade', 'wp-optimize'),
860 'menu_slug' => 'wpo_mayalso',
861 'function' => array($this, 'display_admin'),
862 'icon' => 'admin-plugins',
863 'create_submenu' => true,
864 'order' => 70,
865 ),
866 );
867
868 $filtered_sub_menu_items = apply_filters('wp_optimize_sub_menu_items', $sub_menu_items);
869
870 if (empty($filtered_sub_menu_items) || !is_array($filtered_sub_menu_items)) {
871 $filtered_sub_menu_items = $sub_menu_items;
872 }
873
874 usort($filtered_sub_menu_items, array($this, 'order_sort'));
875
876 return $filtered_sub_menu_items;
877 }
878
879 /**
880 * Order sorting function
881 *
882 * @param array $a
883 * @param array $b
884 *
885 * @return int
886 */
887 public function order_sort($a, $b) {
888 if ($a['order'] === $b['order']) return 0;
889 return ($a['order'] > $b['order']) ? 1 : -1;
890 }
891
892 /**
893 * Output information message for users who have no permissions to run optimizations.
894 *
895 * @param string $message Message to display
896 */
897 public function prevent_run_optimizations_message($message = '') {
898 if (empty($message)) {
899 $message = __('You have no permissions to run optimizations.', 'wp-optimize');
900 }
901 WP_Optimize()->include_template('info-message.php', false, array('message' => $message));
902 }
903
904 /**
905 * Output information message for users who have no permissions to manage settings.
906 */
907 public function prevent_manage_options_info() {
908 WP_Optimize()->include_template('info-message.php', false, array('message' => __('You have no permissions to manage WP-Optimize settings.', 'wp-optimize')));
909 }
910
911 /**
912 * Output success/error messages from $output array.
913 *
914 * @param array $output ['messages' => success messages, 'errors' => error messages]
915 */
916 private function wpo_render_output_messages($output) {
917 foreach ($output['messages'] as $item) {
918 echo '<div class="updated fade below-h2"><strong>'.esc_html($item).'</strong></div>';
919 }
920
921 foreach ($output['errors'] as $item) {
922 echo '<div class="error fade below-h2"><strong>'.esc_html($item).'</strong></div>';
923 }
924 }
925 }
926 endif;
927