PluginProbe
MainWP Dashboard: Self-hosted WordPress Management for Agencies / 6.2.1
MainWP Dashboard: Self-hosted WordPress Management for Agencies v6.2.1
6.2.2 6.2.1 6.2 6.1.8 6.1.7 6.1.6 6.1.5 6.1.4 6.1.3 6.1.2 6.1.1 6.1 6.0.12 6.0.11 4.6.0.1 5.0 5.0.1 5.0.2 5.0.3 5.0.3.1 5.0.3.2 5.1 5.1.1 5.2 5.2.1 All 155 releases
← All changes | class/class-mainwp-system.php +948 -86 5.1.1 → 6.2.1 View file →
@@ -6,9 +6,17 @@
6 6 */
7 7
8 8 namespace MainWP\Dashboard;
9 9
10 +use MainWP\Dashboard\Module\Log\Log_Manage_Insights_Events_Page;
11 +
12 +// Exit if accessed directly.
13 +if ( ! defined( 'ABSPATH' ) ) {
14 + exit;
15 +}
16 +
10 17 // phpcs:disable Generic.Metrics.CyclomaticComplexity -- complexity.
18 +// phpcs:disable plugin_updater_detected -- not a self-updater; injects update data exclusively for licensed MainWP premium extensions hosted on mainwp.com.
11 19
12 20 const MAINWP_VIEW_PER_SITE = 1;
13 21 const MAINWP_VIEW_PER_PLUGIN_THEME = 0;
14 22 const MAINWP_VIEW_PER_GROUP = 2;
@@ -26,9 +34,9 @@
26 34 * Public static variable to hold the current plugin version.
27 35 *
28 36 * @var string Current plugin version.
29 37 */
30 - public static $version = '5.1.1'; // NOSONAR.
38 + public static $version = '6.2.1'; // NOSONAR.
31 39
32 40 /**
33 41 * Private static variable to hold the single instance of the class.
34 42 *
@@ -55,9 +63,9 @@
55 63 * Private variable to hold the check update version number.
56 64 *
57 65 * @var string The plugin current update version.
58 66 */
59 - private $check_ver_update = '0.0.5';
67 + private $check_ver_update = '0.0.8';
60 68
61 69 /**
62 70 * Private variable to hold the plugin slug (mainwp/mainwp.php)
63 71 *
@@ -64,9 +72,18 @@
64 72 * @var string Plugin slug.
65 73 */
66 74 private $plugin_slug;
67 75
76 +
68 77 /**
78 + * Private variable to hold the defer js handle.
79 + *
80 + * @var array Defer js handle.
81 + */
82 + private static $defer_js_handle = array();
83 +
84 +
85 + /**
69 86 * Method instance()
70 87 *
71 88 * Create a public static instance.
72 89 *
@@ -117,12 +134,13 @@
117 134 static::$instance = $this;
118 135
119 136 MainWP_Execution_Helper::instance()->init_exec_time();
120 137
121 - $loader = new MainWP_Includes();
122 - $loader->includes();
138 + $includer = new MainWP_Includes();
139 + $includer->includes();
123 140
124 141 MainWP_Keys_Manager::auto_load_files();
142 + MainWP_Keys_Manager::register_migration_hooks();
125 143
126 144 $this->load_all_options();
127 145
128 146 $this->update_install();
@@ -127,14 +145,12 @@
127 145
128 146 $this->update_install();
129 147 $this->plugin_slug = plugin_basename( $mainwp_plugin_file );
130 148
149 + add_action( 'shutdown', array( $this, 'hook_wp_shutdown' ) );
150 +
131 151 do_action( 'mainwp_system_init' );
132 152
133 - // includes rest api work.
134 - require_once 'class-mainwp-rest-api.php'; // NOSONAR - WP compatible.
135 - Rest_Api::instance()->init();
136 -
137 153 if ( is_admin() ) {
138 154 include_once ABSPATH . 'wp-admin' . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'plugin.php'; // NOSONAR - WP compatible.
139 155 $pluginData = get_plugin_data( $mainwp_plugin_file, true, false ); // to fix issue of user language setting.
140 156 $this->current_version = $pluginData['Version'];
@@ -151,8 +167,13 @@
151 167 if ( ! empty( $currentVersion ) && version_compare( $currentVersion, '5.0.2', '<' ) && version_compare( $this->current_version, '5.0.2', '>=' ) ) {
152 168 add_action( 'mainwp_after_header', array( MainWP_System_View::get_class_name(), 'mainwp_ver502_update_notice' ) );
153 169 }
154 170
171 + // Use 6.0.12 as the lower bound so 6.1-er.x builds trigger this notice.
172 + if ( ! empty( $currentVersion ) && version_compare( $currentVersion, '6.1', '<' ) && version_compare( $currentVersion, '6.0.12', '>' ) ) {
173 + add_action( 'mainwp_after_header', array( MainWP_System_View::get_class_name(), 'mainwp_ver61_update_notice' ) );
174 + }
175 +
155 176 MainWP_Utility::update_option( 'mainwp_plugin_version', $this->current_version );
156 177 }
157 178
158 179 if ( ! defined( 'MAINWP_VERSION' ) ) {
@@ -187,13 +208,14 @@
187 208 MainWP_Extensions_Groups::init();
188 209
189 210 $systemHandler = MainWP_System_Handler::instance();
190 211
191 - add_action( 'plugins_loaded', array( &$this, 'localization' ) );
192 - add_filter( 'site_transient_update_plugins', array( $systemHandler, 'check_update_custom' ) );
193 - add_filter( 'pre_set_site_transient_update_plugins', array( $systemHandler, 'pre_check_update_custom' ) );
212 + add_action( 'init', array( &$this, 'localization' ) );
213 + add_filter( 'site_transient_update_plugins', array( $systemHandler, 'check_update_custom' ) ); // phpcs:ignore PluginCheck.CodeAnalysis.Sniffs.UpdatingPluginTransientFound -- not a self-updater; injects update data exclusively for licensed MainWP premium extensions (hosted on mainwp.com), not for the Dashboard plugin itself.
214 + add_filter( 'pre_set_site_transient_update_plugins', array( $systemHandler, 'pre_check_update_custom' ) ); // phpcs:ignore PluginCheck.CodeAnalysis.Sniffs.UpdatingPluginTransientFound -- same as above; pre-populates update info for MainWP premium extensions before WordPress saves the transient.
194 215 add_filter( 'plugins_api', array( $systemHandler, 'plugins_api_extension_info' ), 10, 3 );
195 216 add_filter( 'plugins_api_result', array( $systemHandler, 'plugins_api_wp_plugins_api_result' ), 10, 3 );
217 + add_filter( 'upgrader_pre_download', array( $systemHandler, 'hook_refresh_trusted_extension_package_url' ), 10, 4 );
196 218
197 219 $this->metaboxes = new MainWP_Meta_Boxes();
198 220
199 221 MainWP_Overview::get();
@@ -199,12 +221,14 @@
199 221 MainWP_Overview::get();
200 222 MainWP_Client_Overview::instance();
201 223
202 224 MainWP_Manage_Sites::init();
225 + MainWP_Uptime_Monitoring_Handle::instance();
203 226
204 227 MainWP_Hooks::get_instance();
205 228 MainWP_Menu::get_instance();
206 229
230 + add_action( 'plugins_loaded', array( $this, 'plugins_loaded' ), 9 );
207 231 add_action( 'admin_menu', array( MainWP_Menu::get_class_name(), 'init_mainwp_menus' ) );
208 232 add_filter( 'admin_footer', array( &$this, 'admin_footer' ), 15 );
209 233 add_action( 'admin_head', array( MainWP_System_View::get_class_name(), 'admin_head' ) );
210 234 add_action( 'admin_enqueue_scripts', array( &$this, 'admin_enqueue_styles' ) );
@@ -215,12 +239,15 @@
215 239 MainWP_Bulk_Post::get_instance();
216 240
217 241 add_action( 'admin_init', array( &$this, 'admin_init' ), 20 );
218 242 add_action( 'admin_init', array( $this, 'hook_admin_update_check' ) );
243 + add_action( 'admin_init', array( $this, 'admin_init_update' ) );
219 244 add_action( 'after_setup_theme', array( &$this, 'after_setup_theme' ) );
220 245
221 246 add_action( 'init', array( &$this, 'parse_init' ) );
247 + add_action( 'init', array( &$this, 'init_jobs' ) );
222 248 add_action( 'init', array( &$this, 'init' ), 9999 );
249 +
223 250 add_action( 'admin_init', array( $this, 'admin_redirects' ) );
224 251 add_action( 'current_screen', array( &$this, 'current_screen_redirects' ), 15 );
225 252 add_filter( 'plugin_action_links', array( $this, 'hook_plugin_action_links' ), 10, 4 );
226 253 add_action( 'admin_menu', array( &$this, 'admin_menu' ) );
@@ -229,10 +256,8 @@
229 256 add_action( 'wp_logout', array( &$this, 'clear_sessions' ) );
230 257
231 258 MainWP_Install_Bulk::init();
232 259
233 - MainWP_System_Cron_Jobs::instance()->init_cron_jobs();
234 -
235 260 add_action( 'mainwp_after_header', array( MainWP_System_View::get_class_name(), 'admin_notices' ) );
236 261 add_action( 'admin_notices', array( MainWP_System_View::get_class_name(), 'wp_admin_notices' ) );
237 262 add_action( 'wp_mail_failed', array( &$this, 'wp_mail_failed' ) );
238 263
@@ -259,8 +284,9 @@
259 284 MainWP_Manage_Backups::init();
260 285 }
261 286 MainWP_Manage_Groups::init();
262 287 MainWP_User::init();
288 + MainWP_Password_Policy_Settings::init();
263 289 MainWP_Page::init();
264 290 MainWP_Themes::init();
265 291 MainWP_Plugins::init();
266 292 MainWP_Updates_Overview::init();
@@ -265,16 +291,27 @@
265 291 MainWP_Plugins::init();
266 292 MainWP_Updates_Overview::init();
267 293 MainWP_Client::init();
268 294 MainWP_Rest_Api_Page::init();
269 - MainWP_Non_MainWP_Actions::instance();
295 + MainWP_Logger::instance();
270 296
297 + if ( class_exists( '\MainWP\Dashboard\Module\Log\Log_Manage_Insights_Events_Page' ) ) {
298 + Log_Manage_Insights_Events_Page::instance();
299 + }
300 +
301 + MainWP_Uptime_Monitoring_Schedule::instance();
302 +
271 303 if ( defined( 'WP_CLI' ) && WP_CLI ) {
272 304 MainWP_WP_CLI_Command::init();
273 305 }
274 - if ( defined( 'DOING_CRON' ) && DOING_CRON && isset( $_GET['mainwp_run'] ) && 'test' === $_GET['mainwp_run'] ) { // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
275 - add_action( 'init', array( MainWP_System_Cron_Jobs::instance(), 'cron_active' ), PHP_INT_MAX );
276 - }
306 + MainWP_Unhooks_Helper::instance();
307 + MainWP_Cache_Warm_Helper::instance();
308 + MainWP_System_Utility::instance();
309 +
310 + add_action(
311 + 'wp_ajax_nopriv_mainwp_self_connect',
312 + array( MainWP_Post_Handler::instance(), 'ajax_self_connect' )
313 + );
277 314 }
278 315
279 316 /**
280 317 * Method get_dashboard_version()
@@ -287,8 +324,19 @@
287 324 return static::$version;
288 325 }
289 326
290 327 /**
328 + * Method get_mainwp_version()
329 + *
330 + * Get dashboard version.
331 + *
332 + * @return string $version Version.
333 + */
334 + public static function get_mainwp_version() { //phpcs:ignore -- NOSONAR same function body.
335 + return static::$version;
336 + }
337 +
338 + /**
291 339 * Method load_all_options()
292 340 *
293 341 * Load all wp_options data.
294 342 *
@@ -324,14 +372,15 @@
324 372 'mainwp_extensions',
325 373 'mainwp_activated',
326 374 'mainwp_api_sslVerifyCertificate',
327 375 'mainwp_automaticDailyUpdate',
376 + 'mainwp_pluginAutomaticDailyUpdate',
377 + 'mainwp_themeAutomaticDailyUpdate',
328 378 'mainwp_backup_before_upgrade',
329 379 'mainwp_enableLegacyBackupFeature',
330 380 'mainwp_maximumInstallUpdateRequests',
331 381 'mainwp_maximumSyncRequests',
332 382 'mainwp_primaryBackup',
333 - 'mainwp_security',
334 383 'mainwp_use_favicon',
335 384 'mainwp_wp_cron',
336 385 'mainwp_timeDailyUpdate',
337 386 'mainwp_frequencyDailyUpdate',
@@ -342,14 +391,11 @@
342 391 'mainwp_disable_update_confirmations',
343 392 'mainwp_settings_show_widgets',
344 393 'mainwp_clients_show_widgets',
345 394 'mainwp_settings_show_manage_sites_columns',
346 - 'mainwp_disableSitesChecking',
395 + 'mainwp_individual_uptime_monitoring_schedule_enabled',
347 396 'mainwp_disableSitesHealthMonitoring',
348 - 'mainwp_frequencySitesChecking',
349 397 'mainwp_sitehealthThreshold',
350 - 'mainwp_settings_notification_emails',
351 - 'mainwp_ignore_HTTP_response_status',
352 398 'mainwp_check_http_response',
353 399 'mainwp_extmenu',
354 400 'mainwp_opensslLibLocation',
355 401 'mainwp_notice_wp_mail_failed',
@@ -356,12 +402,22 @@
356 402 'mainwp_show_language_updates',
357 403 'mainwp_logger_check_daily',
358 404 'mainwp_site_actions_notification_enable',
359 405 'mainwp_update_check_version',
406 + 'mainwp_admin_init_update_data',
360 407 'mainwp_setting_demo_mode_enabled',
361 408 'mainwp_log_wait_lasttime',
362 - 'mainwp_updatescheck_start_last_schedule_timestamp',
363 409 'mainwp_cron_license_deactivated_alert_lasttime',
410 + 'mainwp_updatescheck_is_running',
411 + 'mainwp_automatic_updates_is_running',
412 + 'mainwp_frequency_AutoUpdate',
413 + 'mainwp_batch_updates_is_running',
414 + 'mainwp_batch_individual_updates_is_running',
415 + 'mainwp_maximum_uptime_monitoring_requests',
416 + 'mainwp_actionlogs',
417 + 'mainwp_process_uptime_notification_run_status',
418 + 'mainwp_warm_cache_pages_ttl',
419 + 'mainwp_module_log_settings_logs_selection_data',
364 420 );
365 421
366 422 $options = apply_filters( 'mainwp_init_load_all_options', $options );
367 423
@@ -404,12 +460,13 @@
404 460 */
405 461 public function localization() {
406 462 $load = apply_filters( 'mainwp_load_text_domain', true );
407 463 if ( $load ) {
408 - load_plugin_textdomain( 'mainwp', false, dirname( dirname( plugin_basename( __FILE__ ) ) ) . '/languages/' );
464 + load_plugin_textdomain( 'mainwp', false, dirname( dirname( plugin_basename( __FILE__ ) ) ) . '/languages/' ); // phpcs:ignore PluginCheck.CodeAnalysis.DiscouragedFunctions.load_plugin_textdomainFound -- kept for older WP versions (<4.6) and to support local/custom translation files loaded from the plugin's languages directory.
409 465 }
410 466 }
411 467
468 +
412 469 /**
413 470 * Method wp_mail_failed()
414 471 *
415 472 * Check if there has been a wp mail failer.
@@ -496,25 +553,33 @@
496 553 MainWP_System_Cron_Jobs::instance()->cron_updates_check();
497 554 }
498 555
499 556 /**
500 - * Method mainwp_crondeactivatedlicensesalert_action()
557 + * Method mainwp_cron_uptime_monitoring_check_action()
501 558 *
502 - * Run cron activated licenses alert action.
559 + * Run cron uptime monitoring check action.
503 560 */
504 - public function mainwp_crondeactivatedlicensesalert_action() {
505 - MainWP_System_Cron_Jobs::instance()->cron_deactivated_licenses_alert();
561 + public function mainwp_cron_uptime_monitoring_check_action() {
562 + MainWP_Uptime_Monitoring_Schedule::instance()->cron_uptime_check();
506 563 }
507 564
565 + /**
566 + * Method mainwp_cron_perform_general_schedules_action()
567 + *
568 + * Run cron uptime monitoring check action.
569 + */
570 + public function mainwp_cron_perform_general_schedules_action() {
571 + MainWP_System_Cron_Jobs::instance()->cron_perform_general_process();
572 + }
573 +
574 +
508 575 /**
509 - * Method mainwp_croncheckstatus_action()
576 + * Method mainwp_crondeactivatedlicensesalert_action()
510 577 *
511 - * Run cron check sites status action.
512 - *
513 - * @uses \MainWP\Dashboard\MainWP_System_Cron_Jobs::cron_check_websites_status()
578 + * Run cron activated licenses alert action.
514 579 */
515 - public function mainwp_croncheckstatus_action() {
516 - MainWP_System_Cron_Jobs::instance()->cron_check_websites_status();
580 + public function mainwp_crondeactivatedlicensesalert_action() {
581 + MainWP_System_Cron_Jobs::instance()->cron_deactivated_licenses_alert();
517 582 }
518 583
519 584 /**
520 585 * Method mainwp_cronchecksitehealth_action()
@@ -550,45 +615,43 @@
550 615 *
551 616 * @return boolean ture|false.
552 617 */
553 618 public static function is_mainwp_site_page() {
619 + $is_page = false;
554 620 //phpcs:disable WordPress.Security.NonceVerification.Recommended
555 - if ( isset( $_GET['page'] ) && 'CostTrackerAdd' !== $_GET['page'] && ( ( ( isset( $_GET['id'] ) && ! empty( $_GET['id'] ) ) || ( isset( $_GET['dashboard'] ) && ! empty( $_GET['dashboard'] ) ) || ( isset( $_GET['updateid'] ) && ! empty( $_GET['updateid'] ) ) || ( isset( $_GET['emailsettingsid'] ) && ! empty( $_GET['emailsettingsid'] ) ) || ( isset( $_GET['scanid'] ) && ! empty( $_GET['scanid'] ) ) ) || ( 'ServerInformation' === $_GET['page'] || 'ServerInformationCron' === $_GET['page'] || 'ErrorLog' === $_GET['page'] || 'ActionLogs' === $_GET['page'] || 'PluginPrivacy' === $_GET['page'] || 'Settings' === $_GET['page'] || 'SettingsAdvanced' === $_GET['page'] || 'SettingsEmail' === $_GET['page'] || 'MainWPTools' === $_GET['page'] || 'SettingsInsights' === $_GET['page'] || 'SettingsApiBackups' === $_GET['page'] ) ) ) {
556 - return true;
621 + if ( isset( $_GET['page'] ) && 'CostTrackerAdd' !== $_GET['page'] && ( ( ( isset( $_GET['id'] ) && ! empty( $_GET['id'] ) ) || ( isset( $_GET['dashboard'] ) && ! empty( $_GET['dashboard'] ) ) || ( isset( $_GET['updateid'] ) && ! empty( $_GET['updateid'] ) ) || ( isset( $_GET['monitor_wpid'] ) && ! empty( $_GET['monitor_wpid'] ) ) || ( isset( $_GET['emailsettingsid'] ) && ! empty( $_GET['emailsettingsid'] ) ) || ( isset( $_GET['scanid'] ) && ! empty( $_GET['scanid'] ) ) ) || ( 'ServerInformation' === $_GET['page'] || 'ServerInformationCron' === $_GET['page'] || 'ErrorLog' === $_GET['page'] || 'ActionLogs' === $_GET['page'] || 'PluginPrivacy' === $_GET['page'] || 'Settings' === $_GET['page'] || 'SettingsAdvanced' === $_GET['page'] || 'SettingsEmail' === $_GET['page'] || 'PremiumUpdates' === $_GET['page'] || 'MainWPTools' === $_GET['page'] || 'SettingsInsights' === $_GET['page'] || 'SettingsApiBackups' === $_GET['page'] || 'MonitoringSettings' === $_GET['page'] ) ) ) {
622 + $is_page = true;
557 623 }
558 624 //phpcs:enable
559 - return false;
560 - }
561 625
562 - /**
563 - * Method init()
564 - *
565 - * Instantiate Plugin.
566 - */
567 - public function init() { //phpcs:ignore -- NOSONAR - complex.
568 -
569 626 /**
570 - * MainWP disabled menu items array.
627 + * Hook mainwp_is_mainwp_site_page.
571 628 *
572 - * @global object $_mainwp_disable_menus_items
629 + * @since 5.4.1
573 630 */
574 - global $_mainwp_disable_menus_items;
631 + return apply_filters( 'mainwp_is_mainwp_site_page', $is_page );
632 + }
575 633
576 - $_mainwp_disable_menus_items = apply_filters( 'mainwp_disablemenuitems', $_mainwp_disable_menus_items );
577 634
635 + /**
636 + * Method plugins_loaded()
637 + *
638 + * Load plugin text domain.
639 + */
640 + public function plugins_loaded() { // phpcs:ignore -- NOSONAR - complex.
578 641 /**
579 - * Filter: mainwp_main_menu_disable_menu_items
642 + * Action: mainwp_system_plugins_loaded
580 643 *
581 - * Filters disabled MainWP navigation items.
644 + * Fires after all plugins are loaded.
582 645 *
583 - * @since Unknown
646 + * @since 6.1.0
584 647 */
585 - $_mainwp_disable_menus_items = apply_filters( 'mainwp_main_menu_disable_menu_items', $_mainwp_disable_menus_items );
648 + do_action( 'mainwp_system_plugins_loaded' );
586 649
587 650 if ( ! function_exists( 'MainWP\Dashboard\mainwp_current_user_have_right' ) ) {
588 651
589 652 /**
590 - * Method mainwp_current_user_have_right()
653 + * Method \mainwp_current_user_can()
591 654 *
592 655 * Check permission level by hook mainwp_currentusercan of Team Control extension.
593 656 *
594 657 * @param string $cap_type group or type of capabilities.
@@ -625,9 +688,35 @@
625 688
626 689 return apply_filters( 'mainwp_currentusercan', true, $cap_type, $cap );
627 690 }
628 691 }
692 + }
629 693
694 + /**
695 + * Method init()
696 + *
697 + * Instantiate Plugin.
698 + */
699 + public function init() { //phpcs:ignore -- NOSONAR - complex.
700 +
701 + /**
702 + * MainWP disabled menu items array.
703 + *
704 + * @global object $_mainwp_disable_menus_items
705 + */
706 + global $_mainwp_disable_menus_items;
707 +
708 + $_mainwp_disable_menus_items = apply_filters( 'mainwp_disablemenuitems', $_mainwp_disable_menus_items );
709 +
710 + /**
711 + * Filter: mainwp_main_menu_disable_menu_items
712 + *
713 + * Filters disabled MainWP navigation items.
714 + *
715 + * @since Unknown
716 + */
717 + $_mainwp_disable_menus_items = apply_filters( 'mainwp_main_menu_disable_menu_items', $_mainwp_disable_menus_items );
718 +
630 719 MainWP_System_Handler::instance()->handle_settings_post();
631 720 }
632 721
633 722 /**
@@ -680,8 +769,18 @@
680 769 // phpcs:enable
681 770 }
682 771
683 772 /**
773 + * Method init_jobs()
774 + *
775 + * Initiate mainwp schedule jobs.
776 + */
777 + public function init_jobs() {
778 + MainWP_System_Cron_Jobs::instance()->init_cron_jobs();
779 + }
780 +
781 +
782 + /**
684 783 * Method after_setup_theme()
685 784 *
686 785 * After setup theme hook, to support post thumbnails.
687 786 */
@@ -694,19 +793,15 @@
694 793 * Method hook_admin_update_check()
695 794 */
696 795 public function hook_admin_update_check() {
697 796 $current_ver = $this->check_ver_update;
698 - $saved_ver = get_option( 'mainwp_update_check_version', false );
797 + $saved_ver = get_option( 'mainwp_update_check_version', '' );
699 798
700 - if ( false === $saved_ver ) {
701 - return;
702 - }
703 -
704 799 if ( version_compare( $saved_ver, $current_ver, '=' ) ) {
705 800 return;
706 801 }
707 802
708 - if ( version_compare( $saved_ver, '0.0.4', '<' ) ) {
803 + if ( ! empty( $saved_ver ) && version_compare( $saved_ver, '0.0.4', '<' ) ) {
709 804 $sched = wp_next_scheduled( 'mainwp_cronstats_action' );
710 805 if ( ! empty( $sched ) ) {
711 806 wp_unschedule_event( $sched, 'mainwp_cronstats_action' );
712 807 }
@@ -713,9 +808,9 @@
713 808 global $wpdb;
714 809 $wpdb->query( 'DELETE FROM ' . $wpdb->usermeta . ' WHERE meta_key = "mainwp_widgets_sorted_toplevel_page_mainwp_tab" OR meta_key="mainwp_settings_show_widgets"' );//phpcs:ignore -- safe.
715 810 }
716 811
717 - if ( version_compare( $saved_ver, '0.0.5', '<' ) ) {
812 + if ( ! empty( $saved_ver ) && version_compare( $saved_ver, '0.0.5', '<' ) ) {
718 813 $all_ext = MainWP_Extensions_View::get_available_extensions();
719 814 foreach ( $all_ext as $slug => $info ) {
720 815 $data = MainWP_Api_Manager::instance()->get_activation_info( $slug );
721 816 if ( is_array( $data ) && isset( $data['api_key'] ) ) {
@@ -726,12 +821,73 @@
726 821 }
727 822 update_option( 'mainwp_extensions_all_activation_cached', '' );
728 823 }
729 824
825 + if ( version_compare( $saved_ver, '0.0.8', '<' ) ) {
826 + static::handle_admin_perform_update( 'attempted_repair_primary_monitors' ); // init attempted repair.
827 + }
828 +
730 829 MainWP_Utility::update_option( 'mainwp_update_check_version', $current_ver );
731 830 }
732 831
832 +
733 833 /**
834 + * Method admin_init_update()
835 + */
836 + public function admin_init_update() {
837 + static::handle_admin_perform_update();
838 + }
839 +
840 +
841 + /**
842 + * Method handle_admin_perform_update()
843 + *
844 + * @param string $action Init action.
845 + */
846 + public function handle_admin_perform_update( $action = '' ) {
847 +
848 + $update_actions = get_option( 'mainwp_admin_init_update_data' );
849 +
850 + /**
851 + * Filters the update actions.
852 + *
853 + * @param array $update_actions The available update actions.
854 + * @param string $action The current update action.
855 + *
856 + * @since 6.2.1
857 + *
858 + * @return array The filtered update actions.
859 + */
860 + $update_actions = apply_filters( 'mainwp_admin_init_update_data', $update_actions, $action );
861 +
862 + if ( ! empty( $action ) ) {
863 + if ( ! is_array( $update_actions ) ) {
864 + $update_actions = array();
865 + }
866 + if ( 'attempted_repair_primary_monitors' === $action ) {
867 + $update_actions['attempted_repair_primary_monitors'] = 0;
868 + }
869 + }
870 +
871 + if ( is_array( $update_actions ) ) {
872 + $update = false;
873 + if ( isset( $update_actions['attempted_repair_primary_monitors'] ) ) {
874 + $result = MainWP_DB_Uptime_Monitoring::instance()->repair_missing_primary_monitors( $update_actions['attempted_repair_primary_monitors'] );
875 + if ( is_array( $result ) && ! empty( $result['attempted'] ) ) {
876 + $update_actions['attempted_repair_primary_monitors'] = $result['attempted'];
877 + } else {
878 + unset( $update_actions['attempted_repair_primary_monitors'] );
879 + }
880 + $update = true;
881 + }
882 +
883 + if ( $update ) {
884 + MainWP_Utility::update_option( 'mainwp_admin_init_update_data', $update_actions );
885 + }
886 + }
887 + }
888 +
889 + /**
734 890 * Method admin_init()
735 891 *
736 892 * Do nothing if current user is not an Admin else display the page.
737 893 *
@@ -782,8 +938,9 @@
782 938 MainWP_Post_Plugin_Theme_Handler::instance()->init();
783 939 MainWP_Post_Extension_Handler::instance()->init();
784 940 MainWP_Post_Backup_Handler::instance()->init();
785 941 MainWP_Manage_Sites_Filter_Segment::get_instance()->admin_init();
942 + MainWP_Ui_Manage_Widgets_Layout::get_instance()->admin_init();
786 943
787 944 /**
788 945 * Filter: mainwp_ui_use_wp_calendar
789 946 *
@@ -799,9 +956,14 @@
799 956 $en_params = array( 'jquery-ui-dialog' );
800 957 if ( $use_wp_datepicker ) {
801 958 $en_params[] = 'jquery-ui-datepicker';
802 959 }
960 +
961 + static::$defer_js_handle = array_merge( static::$defer_js_handle, array( 'mainwp' ) );
962 +
803 963 wp_enqueue_script( 'mainwp', MAINWP_PLUGIN_URL . 'assets/js/mainwp.js', $en_params, $this->current_version, true );
964 + wp_enqueue_script( 'mainwp-cache-warm', MAINWP_PLUGIN_URL . 'assets/js/mainwp-cache-warm.js', array(), $this->current_version, true );
965 +
804 966 $disable_backup_checking = true; // removed option.
805 967 $mainwpParams = array(
806 968 'image_url' => MAINWP_PLUGIN_URL . 'assets/images/',
807 969 'backup_before_upgrade' => 1 === (int) get_option( 'mainwp_backup_before_upgrade' ),
@@ -812,11 +974,15 @@
812 974 'time_format' => get_option( 'time_format' ),
813 975 'installedBulkSettingsManager' => is_plugin_active( 'mainwp-bulk-settings-manager/mainwp-bulk-settings-manager.php' ) ? 1 : 0,
814 976 'maximumSyncRequests' => ( get_option( 'mainwp_maximumSyncRequests' ) === false ) ? 8 : get_option( 'mainwp_maximumSyncRequests' ),
815 977 'maximumInstallUpdateRequests' => ( get_option( 'mainwp_maximumInstallUpdateRequests' ) === false ) ? 3 : get_option( 'mainwp_maximumInstallUpdateRequests' ),
978 + 'maximumUptimeMonitoringRequests' => (int) get_option( 'mainwp_maximum_uptime_monitoring_requests', 10 ),
816 979 '_wpnonce' => wp_create_nonce( 'mainwp-admin-nonce' ),
980 + 'quickThemeChangeNonce' => wp_create_nonce( 'mainwp_quick_theme_change' ),
817 981 'demoMode' => MainWP_Demo_Handle::is_demo_mode() ? 1 : 0,
818 982 'roll_ui_icon' => MainWP_Updates_Helper::get_roll_icon( '', true ),
983 + 'admin_url_base' => admin_url(),
984 + 'mainwpVersion' => static::$version,
819 985 );
820 986 wp_localize_script( 'mainwp', 'mainwpParams', $mainwpParams );
821 987
822 988 $mainwpTranslations = MainWP_System_View::get_mainwp_translations();
@@ -833,20 +999,22 @@
833 999 wp_enqueue_script( 'thickbox' );
834 1000 wp_enqueue_script( 'user-profile' );
835 1001 wp_enqueue_style( 'thickbox' );
836 1002
837 - $load_gridster = false;
1003 + $load_gridstack = false;
838 1004
839 1005 // phpcs:disable WordPress.Security.NonceVerification
840 1006 if ( ( isset( $_GET['page'] ) && ( 'mainwp_tab' === $_GET['page'] || ( 'managesites' === $_GET['page'] && isset( $_GET['dashboard'] ) ) ) ) || ( isset( $_GET['page'] ) && 'ManageClients' === $_GET['page'] && isset( $_GET['client_id'] ) ) || ( isset( $_GET['page'] ) && 0 === strpos( wp_unslash( $_GET['page'] ), 'ManageSites' ) ) ) { //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- individual page.
841 - $load_gridster = true;
1007 + $load_gridstack = true;
842 1008 }
843 1009
844 - $load_gridster = apply_filters( 'mainwp_enqueue_script_gridster', $load_gridster );
1010 + // compatible filter.
1011 + $load_gridstack = apply_filters( 'mainwp_enqueue_script_gridster', $load_gridstack );
845 1012
846 - if ( $load_gridster ) {
847 - wp_enqueue_script( 'gridster', MAINWP_PLUGIN_URL . 'assets/js/gridster/jquery.dsmorse-gridster.js', array(), $this->current_version, true );
848 - wp_enqueue_style( 'gridster', MAINWP_PLUGIN_URL . 'assets/js/gridster/jquery.gridster.min.css', array(), $this->current_version );
1013 + if ( $load_gridstack ) {
1014 + static::$defer_js_handle[] = 'mainwp_gridstack';
1015 + wp_enqueue_script( 'mainwp_gridstack', MAINWP_PLUGIN_URL . 'assets/js/gridstack/gridstack-all.js', array( 'jquery' ), $this->current_version, true );
1016 + wp_enqueue_style( 'mainwp_gridstack', MAINWP_PLUGIN_URL . 'assets/js/gridstack/gridstack.min.css', array(), $this->current_version );
849 1017 }
850 1018
851 1019 if ( isset( $_GET['page'] ) && ( 'managesites' === $_GET['page'] || 'MonitoringSites' === $_GET['page'] || 'ManageGroups' === $_GET['page'] ) ) { //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
852 1020 wp_enqueue_script( 'preview', MAINWP_PLUGIN_URL . 'assets/js/preview.js', array(), $this->current_version, true );
@@ -863,9 +1031,34 @@
863 1031 remove_action( 'admin_notices', 'update_nag', 3 );
864 1032 }
865 1033 }
866 1034
1035 +
867 1036 /**
1037 + * Method hook_wp_shutdown()
1038 + */
1039 + public function hook_wp_shutdown() {
1040 + if ( MainWP_Logger::DISABLED !== (int) get_option( 'mainwp_actionlogs' ) ) {
1041 + $error = error_get_last();
1042 + if ( is_array( $error ) && isset( $error['type'] ) && ( E_ERROR === $error['type'] || E_CORE_ERROR === $error['type'] || E_COMPILE_ERROR === $error['type'] || E_PARSE === $error['type'] ) ) {
1043 + MainWP_Logger::instance()->log_action( '[Fatal ERROR detected=' . print_r( $error, true ) . ']', false, MainWP_Logger::WARNING_COLOR, true ); //phpcs:ignore -- NOSONAR.
1044 + }
1045 + }
1046 + MainWP_Cache_Helper::log_metrics();
1047 +
1048 + /**
1049 + * MainWP shutdown.
1050 + *
1051 + * @since 5.5.
1052 + */
1053 + do_action( 'mainwp_shutdown' );
1054 +
1055 + $exctime = MainWP_Execution_Helper::get_run_time();
1056 + MainWP_Logger::instance()->log_events( 'execution-time', 'Shutdown :: ' . $exctime );
1057 + MainWP_Logger::instance()->log_execution_sync( 'end' );
1058 + }
1059 +
1060 + /**
868 1061 * Method hook_plugin_action_links()
869 1062 *
870 1063 * @param string[] $actions An array of plugin action links. By default this can include
871 1064 * 'activate', 'deactivate', and 'delete'. With Multisite active
@@ -947,9 +1140,9 @@
947 1140 $request_uri = isset( $_SERVER['REQUEST_URI'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
948 1141 $_pos = strlen( $request_uri ) - strlen( '/wp-admin/' );
949 1142 if ( ! empty( $request_uri ) && strpos( $request_uri, '/wp-admin/' ) !== false && strpos( $request_uri, '/wp-admin/' ) === $_pos ) {
950 1143 $referer = wp_get_referer();
951 - if ( ! empty( $referer ) && strpos( $referer, 'wp-login.php?redirect_to' ) !== false && strpos( $referer, '&reauth=1' ) !== false && mainwp_current_user_have_right( 'dashboard', 'access_global_dashboard' ) ) {
1144 + if ( ! empty( $referer ) && strpos( $referer, 'wp-login.php?redirect_to' ) !== false && strpos( $referer, '&reauth=1' ) !== false && \mainwp_current_user_can( 'dashboard', 'access_global_dashboard' ) ) {
952 1145 wp_safe_redirect( admin_url( 'admin.php?page=mainwp_tab' ) );
953 1146 die();
954 1147 }
955 1148 }
@@ -998,14 +1191,15 @@
998 1191 MainWP_Cache::init_cache( $ca ); // to re-set cache.
999 1192 }
1000 1193 }
1001 1194
1195 +
1002 1196 /**
1003 1197 * Method admin_enqueue_scripts()
1004 1198 *
1005 1199 * Enqueue all Mainwp Admin Scripts.
1006 1200 */
1007 - public function admin_enqueue_scripts() {
1201 + public function admin_enqueue_scripts() { // phpcs:ignore -- NOSONAR - complex function.
1008 1202
1009 1203 $load_cust_scripts = false;
1010 1204
1011 1205 /**
@@ -1030,21 +1224,20 @@
1030 1224 wp_enqueue_script( 'mainwp-posts', MAINWP_PLUGIN_URL . 'assets/js/mainwp-posts.js', array(), $this->current_version, true );
1031 1225 wp_enqueue_script( 'mainwp-users', MAINWP_PLUGIN_URL . 'assets/js/mainwp-users.js', array(), $this->current_version, true );
1032 1226 wp_enqueue_script( 'mainwp-clients', MAINWP_PLUGIN_URL . 'assets/js/mainwp-clients.js', array(), $this->current_version, true );
1033 1227 wp_enqueue_script( 'mainwp-extensions', MAINWP_PLUGIN_URL . 'assets/js/mainwp-extensions.js', array(), $this->current_version, true );
1034 - wp_enqueue_script( 'mainwp-moment', MAINWP_PLUGIN_URL . 'assets/js/moment/moment.min.js', array(), $this->current_version, true );
1228 + wp_enqueue_script( 'moment' );
1035 1229 wp_enqueue_script( 'fomantic-ui', MAINWP_PLUGIN_URL . 'assets/js/fomantic-ui/fomantic-ui.js', array( 'jquery' ), $this->current_version, false );
1036 1230
1037 - wp_enqueue_script( 'datatables', MAINWP_PLUGIN_URL . 'assets/js/datatables/dataTables.js', array( 'jquery' ), $this->current_version, false );
1038 - wp_enqueue_script( 'datatables-semanticui', MAINWP_PLUGIN_URL . 'assets/js/datatables/dataTables.semanticui.js', array( 'datatables' ), $this->current_version, false );
1231 + wp_enqueue_script( 'datatables', MAINWP_PLUGIN_URL . 'assets/js/datatables/datatables.min.js', array( 'jquery' ), $this->current_version, false );
1232 + wp_enqueue_script( 'datatables-semanticui', MAINWP_PLUGIN_URL . 'assets/js/datatables/dataTables.semanticui.min.js', array( 'datatables' ), $this->current_version, false );
1039 1233 wp_enqueue_script( 'datatables-select', MAINWP_PLUGIN_URL . 'assets/js/datatables/dataTables.select.min.js', array( 'datatables' ), $this->current_version, false );
1040 - wp_enqueue_script( 'datatables-add-ons', MAINWP_PLUGIN_URL . 'assets/js/datatables/datatables.min.js', array( 'datatables' ), $this->current_version, false );
1234 + wp_enqueue_script( 'datatables-add-ons', MAINWP_PLUGIN_URL . 'assets/js/datatables/add-ons.datatables.min.js', array( 'datatables' ), $this->current_version, false );
1041 1235
1042 - wp_enqueue_script( 'hamburger', MAINWP_PLUGIN_URL . 'assets/js/hamburger/hamburger.js', array( 'jquery' ), $this->current_version, true );
1043 - wp_enqueue_script( 'datatables-natural-sorting', MAINWP_PLUGIN_URL . 'assets/js/sorting/natural.js', array( 'jquery' ), $this->current_version, true );
1236 + wp_enqueue_script( 'datatables-natural-sorting', MAINWP_PLUGIN_URL . 'assets/js/sorting/natural.min.js', array( 'jquery', 'datatables' ), $this->current_version, true );
1044 1237
1045 - wp_enqueue_script( 'mainwp-clipboard', MAINWP_PLUGIN_URL . 'assets/js/clipboard/clipboard.min.js', array( 'jquery' ), $this->current_version, true );
1046 - wp_enqueue_script( 'mainwp-rest-api', MAINWP_PLUGIN_URL . 'assets/js/mainwp-rest-api.js', array(), $this->current_version, true );
1238 + wp_enqueue_script( 'clipboard' );
1239 + wp_enqueue_script( 'mainwp-rest-api', MAINWP_PLUGIN_URL . 'assets/js/mainwp-rest-api.js', array(), time(), true );
1047 1240
1048 1241 if ( isset( $_GET['page'] ) && 'ManageGroups' === $_GET['page'] ) { // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1049 1242 wp_enqueue_script( 'mainwp-groups', MAINWP_PLUGIN_URL . 'assets/js/mainwp-groups.js', array(), $this->current_version, true );
1050 1243 }
@@ -1051,9 +1244,9 @@
1051 1244 $enqueue_scripts = apply_filters( 'mainwp_admin_enqueue_scripts', array() );
1052 1245 if ( is_array( $enqueue_scripts ) && ! empty( $enqueue_scripts['apexcharts'] ) ) {
1053 1246 wp_enqueue_script(
1054 1247 'mainwp-apexcharts',
1055 - MAINWP_PLUGIN_URL . 'assets/js/apexcharts/apexcharts.js',
1248 + MAINWP_PLUGIN_URL . 'assets/js/apexcharts/apexcharts.min.js',
1056 1249 array(
1057 1250 'jquery',
1058 1251 'mainwp',
1059 1252 ),
@@ -1059,24 +1252,633 @@
1059 1252 ),
1060 1253 $this->current_version,
1061 1254 true
1062 1255 );
1256 + static::$defer_js_handle[] = 'mainwp-apexcharts';
1063 1257 }
1064 1258 wp_enqueue_script( 'mainwp-dropzone', MAINWP_PLUGIN_URL . 'assets/js/dropzone/dropzone.min.js', array(), $this->current_version, true );
1259 + wp_enqueue_script( 'mainwp-uptime', MAINWP_PLUGIN_URL . 'assets/js/mainwp-uptime.js', array( 'jquery', 'fomantic-ui' ), $this->current_version, true );
1260 + static::$defer_js_handle = array_merge( static::$defer_js_handle, array( 'mainwp-updates', 'mainwp-managesites-action', 'mainwp-managesites-update', 'mainwp-managesites-import', 'mainwp-plugins-themes', 'mainwp-managesites-import', 'mainwp-plugins-themes', 'mainwp-backups', 'mainwp-posts', 'mainwp-users', 'mainwp-clients', 'fomantic-ui', 'datatables', 'datatables-semanticui', 'datatables-select', 'datatables-add-ons', 'mainwp-dropzone', 'mainwp-uptime' ) );
1261 +
1065 1262 }
1066 1263
1067 1264 if ( $load_cust_scripts ) {
1265 + static::$defer_js_handle[] = 'fomantic-ui';
1068 1266 wp_enqueue_script( 'fomantic-ui', MAINWP_PLUGIN_URL . 'assets/js/fomantic-ui/fomantic-ui.js', array( 'jquery' ), $this->current_version, true );
1069 1267 }
1070 1268
1071 1269 wp_enqueue_script( 'mainwp-ui', MAINWP_PLUGIN_URL . 'assets/js/mainwp-ui.js', array(), $this->current_version, true );
1270 + wp_localize_script(
1271 + 'mainwp-ui',
1272 + 'mainwpWidgetLayout',
1273 + array(
1274 + 'openNonce' => wp_create_nonce( 'mainwp-admin-nonce' ),
1275 + )
1276 + );
1072 1277 wp_enqueue_script( 'mainwp-js-popup', MAINWP_PLUGIN_URL . 'assets/js/mainwp-popup.js', array(), $this->current_version, true );
1073 1278 // to support extension uploader.
1074 1279 wp_enqueue_script( 'mainwp-fileuploader', MAINWP_PLUGIN_URL . 'assets/js/fileuploader.js', array(), $this->current_version ); // phpcs:ignore -- fileuploader scripts need to load at header.
1075 1280 wp_enqueue_script( 'mainwp-filesaver', MAINWP_PLUGIN_URL . 'assets/js/FileSaver.js', array(), $this->current_version, true );
1281 +
1282 + static::$defer_js_handle[] = 'mainwp-ui';
1283 +
1284 + if ( is_array( static::$defer_js_handle ) ) {
1285 + $defer_handle = array_filter( array_unique( static::$defer_js_handle ) );
1286 + foreach ( $defer_handle as $h ) {
1287 + if ( wp_script_is( $h, 'enqueued' ) || wp_script_is( $h, 'registered' ) ) {
1288 + wp_script_add_data( $h, 'strategy', 'defer' ); // adds defer to <script> tag.
1289 + }
1290 + }
1291 + }
1292 +
1293 + $this->enqueue_command_palette_script();
1076 1294 }
1077 1295
1078 1296 /**
1297 + * Enqueue the MainWP command palette integration.
1298 + */
1299 + private function enqueue_command_palette_script() {
1300 +
1301 + if ( ! wp_script_is( 'wp-core-commands', 'enqueued' ) ) {
1302 + return;
1303 + }
1304 +
1305 + $palette_data = $this->get_command_palette_data();
1306 +
1307 + if ( empty( $palette_data['commands'] ) && empty( $palette_data['unregister'] ) ) {
1308 + return;
1309 + }
1310 +
1311 + wp_enqueue_script(
1312 + 'mainwp-command-palette',
1313 + MAINWP_PLUGIN_URL . 'assets/js/mainwp-command-palette.js',
1314 + array( 'wp-core-commands', 'wp-data' ),
1315 + $this->current_version,
1316 + true
1317 + );
1318 +
1319 + wp_add_inline_script(
1320 + 'mainwp-command-palette',
1321 + 'window.mainwpCommandPalette = ' . wp_json_encode( $palette_data, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) . ';',
1322 + 'before'
1323 + );
1324 + }
1325 +
1326 + /**
1327 + * Build the MainWP command palette configuration.
1328 + *
1329 + * @return array<string, array<int, mixed>> Command palette configuration.
1330 + */
1331 + private function get_command_palette_data() {
1332 + $registered_pages = $this->get_command_palette_registered_pages();
1333 + $registered_page_urls = array();
1334 +
1335 + foreach ( $registered_pages as $slug => $page_data ) {
1336 + $registered_page_urls[ $slug ] = $page_data['url'];
1337 + }
1338 +
1339 + $commands = $this->get_command_palette_menu_commands( $registered_pages );
1340 +
1341 + if ( empty( $commands ) ) {
1342 + return array(
1343 + 'commands' => array(),
1344 + 'unregister' => array(),
1345 + );
1346 + }
1347 +
1348 + $commands = apply_filters( 'mainwp_command_palette_commands', $commands, $registered_page_urls );
1349 +
1350 + $unregister = array( 'mainwp_tab' );
1351 + foreach ( array_keys( $registered_pages ) as $slug ) {
1352 + $unregister[] = 'mainwp_tab-' . $slug;
1353 + }
1354 +
1355 + $unregister = apply_filters( 'mainwp_command_palette_unregister', array_values( array_unique( $unregister ) ), $registered_page_urls );
1356 +
1357 + return array(
1358 + 'commands' => array_values( array_filter( $commands ) ),
1359 + 'unregister' => array_values( array_filter( $unregister ) ),
1360 + );
1361 + }
1362 +
1363 + /**
1364 + * Get registered MainWP submenu pages that can be opened from the palette.
1365 + *
1366 + * @return array<string, array<string, mixed>> Registered page map.
1367 + */
1368 + private function get_command_palette_registered_pages() {
1369 + global $submenu;
1370 +
1371 + if ( empty( $submenu['mainwp_tab'] ) || ! is_array( $submenu['mainwp_tab'] ) ) {
1372 + return array();
1373 + }
1374 +
1375 + $registered_pages = array();
1376 +
1377 + foreach ( $submenu['mainwp_tab'] as $submenu_item ) {
1378 + if ( empty( $submenu_item[2] ) || ( ! empty( $submenu_item[1] ) && ! current_user_can( $submenu_item[1] ) ) ) {
1379 + continue;
1380 + }
1381 +
1382 + $menu_slug = (string) $submenu_item[2];
1383 + $menu_url = '';
1384 +
1385 + if ( preg_match( '/\.php($|\?)/', $menu_slug ) || $this->is_command_palette_absolute_url( $menu_slug ) ) {
1386 + $menu_url = $menu_slug;
1387 + } elseif ( ! empty( menu_page_url( $menu_slug, false ) ) ) {
1388 + $menu_url = wp_specialchars_decode( menu_page_url( $menu_slug, false ), ENT_QUOTES );
1389 + }
1390 +
1391 + if ( empty( $menu_url ) ) {
1392 + continue;
1393 + }
1394 +
1395 + $raw_label = isset( $submenu_item[0] ) ? (string) $submenu_item[0] : '';
1396 +
1397 + $registered_pages[ $menu_slug ] = array(
1398 + 'label' => $this->clean_command_palette_label( $raw_label ),
1399 + 'url' => $menu_url,
1400 + 'hidden' => false !== strpos( $raw_label, 'mainwp-hidden' ),
1401 + );
1402 + }
1403 +
1404 + return $registered_pages;
1405 + }
1406 +
1407 + /**
1408 + * Build MainWP command-palette commands from runtime menu data.
1409 + *
1410 + * @param array<string, array<string, mixed>> $registered_pages Registered MainWP pages.
1411 + *
1412 + * @return array<int, array<string, mixed>> Command list.
1413 + */
1414 + private function get_command_palette_menu_commands( $registered_pages ) {
1415 + $menu_nodes = $this->get_command_palette_menu_nodes();
1416 +
1417 + if ( empty( $menu_nodes ) ) {
1418 + $menu_nodes = array();
1419 + }
1420 +
1421 + $nodes_by_id = array();
1422 + $nodes_by_slug = array();
1423 +
1424 + foreach ( $menu_nodes as $node ) {
1425 + $nodes_by_id[ $node['id'] ] = $node;
1426 +
1427 + if ( ! empty( $node['slug_key'] ) && ! isset( $nodes_by_slug[ $node['slug_key'] ] ) ) {
1428 + $nodes_by_slug[ $node['slug_key'] ] = $node['id'];
1429 + }
1430 + }
1431 +
1432 + $commands_by_url = array();
1433 + $command_page_slugs = array();
1434 +
1435 + foreach ( $menu_nodes as $node ) {
1436 + $path_titles = $this->get_command_palette_menu_path_titles( $node, $nodes_by_id, $nodes_by_slug );
1437 +
1438 + if ( empty( $path_titles ) ) {
1439 + continue;
1440 + }
1441 +
1442 + $label = sprintf( __( 'Go to: MainWP > %s', 'mainwp' ), implode( ' > ', $path_titles ) );
1443 +
1444 + $command_name = ! empty( $node['page_slug'] ) && isset( $registered_pages[ $node['page_slug'] ] )
1445 + ? 'mainwp_tab-' . $node['page_slug']
1446 + : 'mainwp-command-' . sanitize_key( ! empty( $node['page_slug'] ) ? $node['page_slug'] : md5( $node['url'] ) );
1447 +
1448 + $command = array(
1449 + 'name' => $command_name,
1450 + 'label' => $label,
1451 + 'url' => $node['url'],
1452 + 'keywords' => $this->get_command_palette_keywords( $path_titles, $node['page_slug'] ),
1453 + 'searchLabel' => $label,
1454 + '_depth' => count( $path_titles ),
1455 + );
1456 +
1457 + if ( ! isset( $commands_by_url[ $node['url'] ] ) || $command['_depth'] > $commands_by_url[ $node['url'] ]['_depth'] ) {
1458 + $commands_by_url[ $node['url'] ] = $command;
1459 + }
1460 +
1461 + if ( ! empty( $node['page_slug'] ) ) {
1462 + $command_page_slugs[ $node['page_slug'] ] = true;
1463 + }
1464 + }
1465 +
1466 + foreach ( $this->get_command_palette_utility_commands( $registered_pages ) as $command ) {
1467 + if ( empty( $command['url'] ) || empty( $command['label'] ) ) {
1468 + continue;
1469 + }
1470 +
1471 + $command['_depth'] = isset( $command['_depth'] ) ? (int) $command['_depth'] : 1;
1472 +
1473 + if (
1474 + ! isset( $commands_by_url[ $command['url'] ] ) ||
1475 + $command['_depth'] >= $commands_by_url[ $command['url'] ]['_depth']
1476 + ) {
1477 + $commands_by_url[ $command['url'] ] = $command;
1478 + }
1479 +
1480 + if ( ! empty( $command['_page_slug'] ) ) {
1481 + $command_page_slugs[ $command['_page_slug'] ] = true;
1482 + }
1483 + }
1484 +
1485 + foreach ( $registered_pages as $page_slug => $page_data ) {
1486 + if (
1487 + isset( $command_page_slugs[ $page_slug ] ) ||
1488 + empty( $page_data['label'] ) ||
1489 + empty( $page_data['url'] ) ||
1490 + ! empty( $page_data['hidden'] )
1491 + ) {
1492 + continue;
1493 + }
1494 +
1495 + if ( isset( $commands_by_url[ $page_data['url'] ] ) ) {
1496 + continue;
1497 + }
1498 +
1499 + $label = sprintf( __( 'Go to: MainWP > %s', 'mainwp' ), $page_data['label'] );
1500 +
1501 + $commands_by_url[ $page_data['url'] ] = array(
1502 + 'name' => 'mainwp_tab-' . $page_slug,
1503 + 'label' => $label,
1504 + 'url' => $page_data['url'],
1505 + 'keywords' => $this->get_command_palette_keywords( array( $page_data['label'] ), $page_slug ),
1506 + 'searchLabel' => $label,
1507 + '_depth' => 1,
1508 + );
1509 + }
1510 +
1511 + foreach ( $commands_by_url as &$command ) {
1512 + unset( $command['_depth'], $command['_page_slug'] );
1513 + }
1514 + unset( $command );
1515 +
1516 + return array_values( $commands_by_url );
1517 + }
1518 +
1519 + /**
1520 + * Build command-palette commands for MainWP pages that do not reliably exist in the global sidebar tree.
1521 + *
1522 + * @param array<string, array<string, mixed>> $registered_pages Registered MainWP pages.
1523 + *
1524 + * @return array<int, array<string, mixed>> Command list.
1525 + */
1526 + private function get_command_palette_utility_commands( $registered_pages ) {
1527 + return array_merge(
1528 + $this->get_command_palette_settings_commands( $registered_pages ),
1529 + $this->get_command_palette_info_commands( $registered_pages )
1530 + );
1531 + }
1532 +
1533 + /**
1534 + * Build Settings-section command palette commands.
1535 + *
1536 + * @param array<string, array<string, mixed>> $registered_pages Registered MainWP pages.
1537 + *
1538 + * @return array<int, array<string, mixed>> Command list.
1539 + */
1540 + private function get_command_palette_settings_commands( $registered_pages ) {
1541 + $commands = array();
1542 +
1543 + foreach ( MainWP_Settings::get_command_palette_items() as $item ) {
1544 + if ( empty( $item['slug'] ) || empty( $item['path_titles'] ) ) {
1545 + continue;
1546 + }
1547 +
1548 + $commands[] = $this->build_command_palette_registered_command(
1549 + $registered_pages,
1550 + $item['slug'],
1551 + $item['path_titles'],
1552 + array( 'mainwp settings' ),
1553 + isset( $item['href'] ) ? $item['href'] : ''
1554 + );
1555 + }
1556 +
1557 + return array_values( array_filter( $commands ) );
1558 + }
1559 +
1560 + /**
1561 + * Build System Info and profile utility command palette commands.
1562 + *
1563 + * @param array<string, array<string, mixed>> $registered_pages Registered MainWP pages.
1564 + *
1565 + * @return array<int, array<string, mixed>> Command list.
1566 + */
1567 + private function get_command_palette_info_commands( $registered_pages ) {
1568 + $commands = array();
1569 +
1570 + foreach ( MainWP_Server_Information::get_command_palette_items() as $item ) {
1571 + if ( empty( $item['slug'] ) || empty( $item['path_titles'] ) ) {
1572 + continue;
1573 + }
1574 +
1575 + $commands[] = $this->build_command_palette_registered_command(
1576 + $registered_pages,
1577 + $item['slug'],
1578 + $item['path_titles'],
1579 + array( 'system info', 'server info' ),
1580 + isset( $item['href'] ) ? $item['href'] : ''
1581 + );
1582 + }
1583 +
1584 + return array_values( array_filter( $commands ) );
1585 + }
1586 +
1587 + /**
1588 + * Build a command palette command for a registered page.
1589 + *
1590 + * @param array<string, array<string, mixed>> $registered_pages Registered MainWP pages.
1591 + * @param string $page_slug Registered page slug.
1592 + * @param array<int, string> $path_titles Breadcrumb path labels.
1593 + * @param array<int, string> $extra_keywords Additional search keywords.
1594 + * @param string $href Optional command href override.
1595 + *
1596 + * @return array<string, mixed>|null Command configuration.
1597 + */
1598 + private function build_command_palette_registered_command( $registered_pages, $page_slug, $path_titles, $extra_keywords = array(), $href = '' ) {
1599 + if ( empty( $registered_pages[ $page_slug ]['url'] ) ) {
1600 + return null;
1601 + }
1602 +
1603 + $path_titles = array_values(
1604 + array_filter(
1605 + array_map(
1606 + array( $this, 'clean_command_palette_label' ),
1607 + is_array( $path_titles ) ? $path_titles : array()
1608 + )
1609 + )
1610 + );
1611 +
1612 + if ( empty( $path_titles ) ) {
1613 + return null;
1614 + }
1615 +
1616 + $keywords = $this->get_command_palette_keywords( $path_titles, $page_slug );
1617 +
1618 + foreach ( $extra_keywords as $keyword ) {
1619 + $keyword = strtolower( $this->clean_command_palette_label( $keyword ) );
1620 +
1621 + if ( ! empty( $keyword ) ) {
1622 + $keywords[] = $keyword;
1623 + }
1624 + }
1625 +
1626 + $label = sprintf( __( 'Go to: MainWP > %s', 'mainwp' ), implode( ' > ', $path_titles ) );
1627 + $url = ! empty( $href ) ? $this->normalize_command_palette_url( $href, $page_slug ) : $registered_pages[ $page_slug ]['url'];
1628 +
1629 + if ( empty( $url ) ) {
1630 + return null;
1631 + }
1632 +
1633 + return array(
1634 + 'name' => 'mainwp_tab-' . $page_slug,
1635 + 'label' => $label,
1636 + 'url' => $url,
1637 + 'keywords' => array_values( array_unique( array_filter( $keywords ) ) ),
1638 + 'searchLabel' => $label,
1639 + '_depth' => count( $path_titles ),
1640 + '_page_slug' => $page_slug,
1641 + );
1642 + }
1643 +
1644 + /**
1645 + * Collect MainWP menu nodes from the runtime left-menu structures.
1646 + *
1647 + * @return array<int, array<string, string>> Menu nodes.
1648 + */
1649 + private function get_command_palette_menu_nodes() {
1650 + global $mainwp_leftmenu, $mainwp_sub_leftmenu;
1651 +
1652 + $left_menu = apply_filters( 'mainwp_main_menu', is_array( $mainwp_leftmenu ) ? $mainwp_leftmenu : array() );
1653 + $sub_left_menu = apply_filters( 'mainwp_main_menu_submenu', is_array( $mainwp_sub_leftmenu ) ? $mainwp_sub_leftmenu : array() );
1654 + $menu_nodes = array();
1655 +
1656 + if ( ! empty( $left_menu['leftbar'] ) && is_array( $left_menu['leftbar'] ) ) {
1657 + foreach ( $left_menu['leftbar'] as $item ) {
1658 + $this->add_command_palette_menu_node(
1659 + $menu_nodes,
1660 + isset( $item[0] ) ? $item[0] : '',
1661 + isset( $item[2] ) ? $item[2] : '',
1662 + isset( $item[1] ) ? $item[1] : '',
1663 + 'mainwp_tab'
1664 + );
1665 + }
1666 + }
1667 +
1668 + foreach ( $left_menu as $parent_key => $items ) {
1669 + if ( 'leftbar' === $parent_key || ! is_array( $items ) ) {
1670 + continue;
1671 + }
1672 +
1673 + foreach ( $items as $item ) {
1674 + $this->add_command_palette_menu_node(
1675 + $menu_nodes,
1676 + isset( $item[0] ) ? $item[0] : '',
1677 + isset( $item[2] ) ? $item[2] : '',
1678 + isset( $item[1] ) ? $item[1] : '',
1679 + $parent_key
1680 + );
1681 + }
1682 + }
1683 +
1684 + if ( ! empty( $sub_left_menu['leftbar'] ) && is_array( $sub_left_menu['leftbar'] ) ) {
1685 + foreach ( $sub_left_menu['leftbar'] as $parent_key => $items ) {
1686 + if ( ! is_array( $items ) ) {
1687 + continue;
1688 + }
1689 +
1690 + foreach ( $items as $item ) {
1691 + $this->add_command_palette_menu_node(
1692 + $menu_nodes,
1693 + isset( $item[0] ) ? $item[0] : '',
1694 + isset( $item[2] ) ? $item[2] : '',
1695 + isset( $item[1] ) ? $item[1] : '',
1696 + $parent_key
1697 + );
1698 + }
1699 + }
1700 + }
1701 +
1702 + foreach ( $sub_left_menu as $parent_key => $items ) {
1703 + if ( 'leftbar' === $parent_key || ! is_array( $items ) ) {
1704 + continue;
1705 + }
1706 +
1707 + foreach ( $items as $item ) {
1708 + $this->add_command_palette_menu_node(
1709 + $menu_nodes,
1710 + isset( $item[0] ) ? $item[0] : '',
1711 + isset( $item[1] ) ? $item[1] : '',
1712 + isset( $item[4] ) ? $item[4] : '',
1713 + $parent_key
1714 + );
1715 + }
1716 + }
1717 +
1718 + return $menu_nodes;
1719 + }
1720 +
1721 + /**
1722 + * Add a single node to the command palette source list.
1723 + *
1724 + * @param array<int, array<string, string>> $menu_nodes Menu nodes.
1725 + * @param string $title Menu title.
1726 + * @param string $href Menu href.
1727 + * @param string $slug Menu slug.
1728 + * @param string $parent_key Parent menu slug.
1729 + */
1730 + private function add_command_palette_menu_node( &$menu_nodes, $title, $href, $slug, $parent_key ) {
1731 + $title = $this->clean_command_palette_label( $title );
1732 + $url = $this->normalize_command_palette_url( $href, $slug );
1733 +
1734 + if ( empty( $title ) || empty( $url ) ) {
1735 + return;
1736 + }
1737 +
1738 + $page_slug = $this->get_command_palette_page_slug_from_url( $url );
1739 + $slug_key = ! empty( $slug ) ? (string) $slug : $page_slug;
1740 +
1741 + $menu_nodes[] = array(
1742 + 'id' => md5( $parent_key . '|' . $slug_key . '|' . $url . '|' . $title ),
1743 + 'parent' => (string) $parent_key,
1744 + 'page_slug' => $page_slug,
1745 + 'slug_key' => $slug_key,
1746 + 'title' => $title,
1747 + 'url' => $url,
1748 + );
1749 + }
1750 +
1751 + /**
1752 + * Build a node breadcrumb from the MainWP menu tree.
1753 + *
1754 + * @param array<string, string> $node Menu node.
1755 + * @param array<string, array<string, string>> $nodes_by_id Menu nodes indexed by id.
1756 + * @param array<string, string> $nodes_by_slug Menu nodes indexed by slug.
1757 + *
1758 + * @return array<int, string> Path titles.
1759 + */
1760 + private function get_command_palette_menu_path_titles( $node, $nodes_by_id, $nodes_by_slug ) {
1761 + $titles = array();
1762 + $current = $node;
1763 + $seen_nodes = array();
1764 +
1765 + while ( is_array( $current ) && ! empty( $current['id'] ) && ! isset( $seen_nodes[ $current['id'] ] ) ) {
1766 + $seen_nodes[ $current['id'] ] = true;
1767 +
1768 + if ( ! empty( $current['title'] ) ) {
1769 + array_unshift( $titles, $current['title'] );
1770 + }
1771 +
1772 + if ( empty( $current['parent'] ) || 'mainwp_tab' === $current['parent'] || ! isset( $nodes_by_slug[ $current['parent'] ] ) ) {
1773 + break;
1774 + }
1775 +
1776 + $parent_id = $nodes_by_slug[ $current['parent'] ];
1777 + $current = isset( $nodes_by_id[ $parent_id ] ) ? $nodes_by_id[ $parent_id ] : array();
1778 + }
1779 +
1780 + return $titles;
1781 + }
1782 +
1783 + /**
1784 + * Build search keywords for a MainWP command.
1785 + *
1786 + * @param array<int, string> $path_titles Path titles.
1787 + * @param string $page_slug Page slug.
1788 + *
1789 + * @return array<int, string> Search keywords.
1790 + */
1791 + private function get_command_palette_keywords( $path_titles, $page_slug = '' ) {
1792 + $keywords = array( 'mainwp' );
1793 +
1794 + foreach ( $path_titles as $title ) {
1795 + $keywords[] = strtolower( $title );
1796 + }
1797 +
1798 + if ( ! empty( $page_slug ) ) {
1799 + $keywords[] = strtolower( str_replace( array( '-', '_' ), ' ', $page_slug ) );
1800 + }
1801 +
1802 + return array_values( array_unique( array_filter( $keywords ) ) );
1803 + }
1804 +
1805 + /**
1806 + * Normalize menu text into readable plain text.
1807 + *
1808 + * @param string $label Raw menu label.
1809 + *
1810 + * @return string Plain-text label.
1811 + */
1812 + private function clean_command_palette_label( $label ) {
1813 + $label = wp_specialchars_decode( wp_strip_all_tags( (string) $label ), ENT_QUOTES );
1814 + $label = preg_replace( '/\s+/', ' ', $label );
1815 +
1816 + return trim( (string) $label );
1817 + }
1818 +
1819 + /**
1820 + * Check whether a command-palette URL is already absolute.
1821 + *
1822 + * @param string $url URL to check.
1823 + *
1824 + * @return bool True when the URL is an absolute HTTP(S) URL.
1825 + */
1826 + private function is_command_palette_absolute_url( $url ) {
1827 + return 1 === preg_match( '/^https?:\/\//i', trim( (string) $url ) );
1828 + }
1829 +
1830 + /**
1831 + * Normalize a MainWP menu href into a usable URL.
1832 + *
1833 + * @param string $href Menu href.
1834 + * @param string $slug Menu slug.
1835 + *
1836 + * @return string Normalized URL.
1837 + */
1838 + private function normalize_command_palette_url( $href, $slug = '' ) {
1839 + $href = trim( wp_specialchars_decode( (string) $href, ENT_QUOTES ) );
1840 + $slug = trim( (string) $slug );
1841 +
1842 + if ( empty( $href ) || '#' === $href || 0 === strpos( $href, 'javascript:' ) ) {
1843 + if ( empty( $slug ) || preg_match( '/\.php($|\?)/', $slug ) || $this->is_command_palette_absolute_url( $slug ) ) {
1844 + return '';
1845 + }
1846 +
1847 + return admin_url( 'admin.php?page=' . $slug );
1848 + }
1849 +
1850 + if ( $this->is_command_palette_absolute_url( $href ) ) {
1851 + return $href;
1852 + }
1853 +
1854 + return admin_url( ltrim( $href, '/' ) );
1855 + }
1856 +
1857 + /**
1858 + * Extract a page slug from a menu URL when one exists.
1859 + *
1860 + * @param string $url Menu URL.
1861 + *
1862 + * @return string Page slug.
1863 + */
1864 + private function get_command_palette_page_slug_from_url( $url ) {
1865 + $query = wp_parse_url( $url, PHP_URL_QUERY );
1866 +
1867 + if ( empty( $query ) ) {
1868 + return '';
1869 + }
1870 +
1871 + parse_str( $query, $query_args );
1872 +
1873 + if ( ! isset( $query_args['page'] ) ) {
1874 + return '';
1875 + }
1876 +
1877 + return preg_replace( '/[^A-Za-z0-9_-]/', '', (string) $query_args['page'] );
1878 + }
1879 +
1880 + /**
1079 1881 * Method admin_enqueue_scripts_fix_conflict()
1080 1882 *
1081 1883 * Enqueue Admin Scripts fix conflict.
1082 1884 */
@@ -1117,14 +1919,12 @@
1117 1919 wp_enqueue_style( 'mainwp-fonts', MAINWP_PLUGIN_URL . 'assets/css/mainwp-fonts.css', array(), $this->current_version );
1118 1920 wp_enqueue_style( 'fomantic-ui', MAINWP_PLUGIN_URL . 'assets/js/fomantic-ui/fomantic-ui.css', array(), $this->current_version );
1119 1921 wp_enqueue_style( 'mainwp-fomantic', MAINWP_PLUGIN_URL . 'assets/css/mainwp-fomantic.css', array(), $this->current_version );
1120 1922
1121 - wp_enqueue_style( 'datatables', MAINWP_PLUGIN_URL . 'assets/js/datatables/dataTables.dataTables.css', array(), $this->current_version );
1122 - wp_enqueue_style( 'datatables-semanticui', MAINWP_PLUGIN_URL . 'assets/js/datatables/dataTables.semanticui.css', array(), $this->current_version );
1923 + wp_enqueue_style( 'datatables', MAINWP_PLUGIN_URL . 'assets/js/datatables/dataTables.dataTables.min.css', array(), $this->current_version );
1924 + wp_enqueue_style( 'datatables-semanticui', MAINWP_PLUGIN_URL . 'assets/js/datatables/dataTables.semanticui.min.css', array(), $this->current_version );
1123 1925 wp_enqueue_style( 'datatables-select', MAINWP_PLUGIN_URL . 'assets/js/datatables/select.semanticui.min.css', array(), $this->current_version );
1124 - wp_enqueue_style( 'datatables-add-ons', MAINWP_PLUGIN_URL . 'assets/js/datatables/datatables.min.css', array(), $this->current_version );
1125 -
1126 - wp_enqueue_style( 'hamburger', MAINWP_PLUGIN_URL . 'assets/js/hamburger/hamburger.css', array(), $this->current_version );
1926 + wp_enqueue_style( 'datatables-add-ons', MAINWP_PLUGIN_URL . 'assets/js/datatables/add-ons.datatables.min.css', array(), $this->current_version );
1127 1927 // to fix conflict layout.
1128 1928 wp_enqueue_style( 'jquery-ui-style', MAINWP_PLUGIN_URL . 'assets/css/1.11.1/jquery-ui.min.css', array(), '1.11.1' );
1129 1929
1130 1930 // load custom MainWP theme.
@@ -1135,10 +1935,14 @@
1135 1935 } elseif ( 'wpadmin' === $selected_theme ) {
1136 1936 wp_enqueue_style( 'mainwp-custom-dashboard-extension-wp-admin-theme', MAINWP_PLUGIN_URL . 'assets/css/themes/mainwp-wpadmin-theme.css', array(), $this->current_version );
1137 1937 } elseif ( 'minimalistic' === $selected_theme ) {
1138 1938 wp_enqueue_style( 'mainwp-custom-dashboard-extension-minimalistic-theme', MAINWP_PLUGIN_URL . 'assets/css/themes/mainwp-minimalistic-theme.css', array(), $this->current_version );
1939 + } elseif ( 'default-2024' === $selected_theme ) {
1940 + wp_enqueue_style( 'mainwp-custom-dashboard-extension-default-2024-theme', MAINWP_PLUGIN_URL . 'assets/css/themes/mainwp-default-2024-theme.css', array(), $this->current_version );
1139 1941 } elseif ( 'default' === $selected_theme ) {
1140 1942 wp_enqueue_style( 'mainwp-custom-dashboard-extension-default-theme', MAINWP_PLUGIN_URL . 'assets/css/themes/mainwp-default-theme.css', array(), $this->current_version );
1943 + } elseif ( 'default-dark' === $selected_theme ) {
1944 + wp_enqueue_style( 'mainwp-custom-dashboard-extension-default-dark-theme', MAINWP_PLUGIN_URL . 'assets/css/themes/mainwp-default-dark-theme.css', array(), $this->current_version );
1141 1945 } else {
1142 1946 $dirs = MainWP_Settings::get_instance()->get_custom_theme_folder();
1143 1947 $custom_theme_url = $dirs[1];
1144 1948 wp_enqueue_style( 'mainwp-custom-dashboard-theme', $custom_theme_url . $selected_theme, array(), $this->current_version );
@@ -1246,9 +2050,9 @@
1246 2050 }
1247 2051 } elseif ( 'UpdatesManage' === $_GET['page'] || 'mainwp_tab' === $_GET['page'] ) { // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1248 2052 $staging_enabled = is_plugin_active( 'mainwp-staging-extension/mainwp-staging-extension.php' ) ? true : false;
1249 2053 if ( $staging_enabled ) {
1250 - $staging_view = MainWP_System_Utility::get_staging_options_sites_view_for_current_users();
2054 + $staging_view = MainWP_System_Utility::get_select_staging_view_sites();
1251 2055 if ( 'staging' === $staging_view ) {
1252 2056 $is_staging = 'yes';
1253 2057 }
1254 2058 }
@@ -1264,10 +2068,8 @@
1264 2068
1265 2069 MainWP_System_View::admin_footer();
1266 2070 MainWP_System_View::render_plugins_install_check();
1267 2071
1268 - MainWP_Menu::init_sub_pages();
1269 -
1270 2072 /**
1271 2073 * MainWP disabled menu items array.
1272 2074 *
1273 2075 * @global object
@@ -1308,8 +2110,17 @@
1308 2110 * Deactivate MainWP.
1309 2111 */
1310 2112 public function deactivation() {
1311 2113 update_option( 'mainwp_extensions_all_activation_cached', '' );
2114 + $useWPCron = ( get_option( 'mainwp_wp_cron' ) === false ) || ( (int) get_option( 'mainwp_wp_cron' ) === 1 );
2115 + if ( $useWPCron ) {
2116 + $jobs = MainWP_System_Cron_Jobs::instance()->get_cron_jobs();
2117 + if ( $jobs ) {
2118 + foreach ( $jobs as $job => $recu ) {
2119 + wp_clear_scheduled_hook( $job );
2120 + }
2121 + }
2122 + }
1312 2123 }
1313 2124
1314 2125 /**
1315 2126 * Method update_install()
@@ -1370,6 +2181,57 @@
1370 2181 * Get MainWP Plugin Slug.
1371 2182 */
1372 2183 public function get_plugin_slug() {
1373 2184 return $this->plugin_slug;
2185 + }
2186 +
2187 + /**
2188 + * Method get_selected_sites_with_allowed_sites.
2189 + *
2190 + * @param array $selected_ids Selected sites IDs.
2191 + * @param array $current_sites Current sites IDs.
2192 + * @return array Not selected but in not allowed sites in current sites ids, and selected sites ids.
2193 + */
2194 + public static function get_selected_sites_with_allowed_sites( $selected_ids, $current_sites_ids = array() ) {
2195 +
2196 + $allowed_sites = apply_filters( 'mainwp_currentuserallowedaccesssites', 'all' );
2197 + if ( 'all' === $allowed_sites ) {
2198 + return $selected_ids;
2199 + }
2200 +
2201 + if ( ! is_array( $selected_ids ) ) {
2202 + $selected_ids = array();
2203 + }
2204 +
2205 + if ( ! is_array( $current_sites_ids ) ) {
2206 + $current_sites_ids = array();
2207 + }
2208 +
2209 + $allowed_sites = MainWP_DB::instance()->get_websites_for_current_user();
2210 + if ( empty( $allowed_sites ) ) {
2211 + return array();
2212 + }
2213 +
2214 + $allowed_ids = array_values(
2215 + array_map(
2216 + function ( $item ) {
2217 + return $item->id;
2218 + },
2219 + $allowed_sites
2220 + )
2221 + );
2222 +
2223 + $client_site_ids = array();
2224 + foreach ( $selected_ids as $id ) {
2225 + if ( in_array( $id, $allowed_ids ) ) {
2226 + $client_site_ids[] = $id;
2227 + }
2228 + }
2229 +
2230 + foreach ( $current_sites_ids as $id ) {
2231 + if ( ! in_array( $id, $selected_ids ) && ! in_array( $id, $allowed_ids ) ) { // If it’s not in the allowed site IDs, the user is not permitted to change it.
2232 + $client_site_ids[] = $id; // keep this site ids.
2233 + }
2234 + }
2235 + return $client_site_ids;
1374 2236 }
1375 2237 }