PluginProbe
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance / 4.5.2
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance v4.5.2
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.5.2, at includes/class-wp-optimize-admin.php

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