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

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