PluginProbe
MainWP Dashboard: Self-hosted WordPress Management for Agencies / 6.2.2
MainWP Dashboard: Self-hosted WordPress Management for Agencies v6.2.2
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 +939 -81 5.2.1 → 6.2.2 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.2.1'; // NOSONAR.
38 + public static $version = '6.2.2'; // 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 *
@@ -121,8 +138,9 @@
121 138 $includer = new MainWP_Includes();
122 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,8 +145,10 @@
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 153 if ( is_admin() ) {
134 154 include_once ABSPATH . 'wp-admin' . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'plugin.php'; // NOSONAR - WP compatible.
@@ -147,8 +167,13 @@
147 167 if ( ! empty( $currentVersion ) && version_compare( $currentVersion, '5.0.2', '<' ) && version_compare( $this->current_version, '5.0.2', '>=' ) ) {
148 168 add_action( 'mainwp_after_header', array( MainWP_System_View::get_class_name(), 'mainwp_ver502_update_notice' ) );
149 169 }
150 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 +
151 176 MainWP_Utility::update_option( 'mainwp_plugin_version', $this->current_version );
152 177 }
153 178
154 179 if ( ! defined( 'MAINWP_VERSION' ) ) {
@@ -183,13 +208,14 @@
183 208 MainWP_Extensions_Groups::init();
184 209
185 210 $systemHandler = MainWP_System_Handler::instance();
186 211
187 - add_action( 'plugins_loaded', array( &$this, 'localization' ) );
188 - add_filter( 'site_transient_update_plugins', array( $systemHandler, 'check_update_custom' ) );
189 - 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.
190 215 add_filter( 'plugins_api', array( $systemHandler, 'plugins_api_extension_info' ), 10, 3 );
191 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 );
192 218
193 219 $this->metaboxes = new MainWP_Meta_Boxes();
194 220
195 221 MainWP_Overview::get();
@@ -195,12 +221,14 @@
195 221 MainWP_Overview::get();
196 222 MainWP_Client_Overview::instance();
197 223
198 224 MainWP_Manage_Sites::init();
225 + MainWP_Uptime_Monitoring_Handle::instance();
199 226
200 227 MainWP_Hooks::get_instance();
201 228 MainWP_Menu::get_instance();
202 229
230 + add_action( 'plugins_loaded', array( $this, 'plugins_loaded' ), 9 );
203 231 add_action( 'admin_menu', array( MainWP_Menu::get_class_name(), 'init_mainwp_menus' ) );
204 232 add_filter( 'admin_footer', array( &$this, 'admin_footer' ), 15 );
205 233 add_action( 'admin_head', array( MainWP_System_View::get_class_name(), 'admin_head' ) );
206 234 add_action( 'admin_enqueue_scripts', array( &$this, 'admin_enqueue_styles' ) );
@@ -211,12 +239,15 @@
211 239 MainWP_Bulk_Post::get_instance();
212 240
213 241 add_action( 'admin_init', array( &$this, 'admin_init' ), 20 );
214 242 add_action( 'admin_init', array( $this, 'hook_admin_update_check' ) );
243 + add_action( 'admin_init', array( $this, 'admin_init_update' ) );
215 244 add_action( 'after_setup_theme', array( &$this, 'after_setup_theme' ) );
216 245
217 246 add_action( 'init', array( &$this, 'parse_init' ) );
247 + add_action( 'init', array( &$this, 'init_jobs' ) );
218 248 add_action( 'init', array( &$this, 'init' ), 9999 );
249 +
219 250 add_action( 'admin_init', array( $this, 'admin_redirects' ) );
220 251 add_action( 'current_screen', array( &$this, 'current_screen_redirects' ), 15 );
221 252 add_filter( 'plugin_action_links', array( $this, 'hook_plugin_action_links' ), 10, 4 );
222 253 add_action( 'admin_menu', array( &$this, 'admin_menu' ) );
@@ -225,10 +256,8 @@
225 256 add_action( 'wp_logout', array( &$this, 'clear_sessions' ) );
226 257
227 258 MainWP_Install_Bulk::init();
228 259
229 - MainWP_System_Cron_Jobs::instance()->init_cron_jobs();
230 -
231 260 add_action( 'mainwp_after_header', array( MainWP_System_View::get_class_name(), 'admin_notices' ) );
232 261 add_action( 'admin_notices', array( MainWP_System_View::get_class_name(), 'wp_admin_notices' ) );
233 262 add_action( 'wp_mail_failed', array( &$this, 'wp_mail_failed' ) );
234 263
@@ -255,8 +284,9 @@
255 284 MainWP_Manage_Backups::init();
256 285 }
257 286 MainWP_Manage_Groups::init();
258 287 MainWP_User::init();
288 + MainWP_Password_Policy_Settings::init();
259 289 MainWP_Page::init();
260 290 MainWP_Themes::init();
261 291 MainWP_Plugins::init();
262 292 MainWP_Updates_Overview::init();
@@ -261,16 +291,27 @@
261 291 MainWP_Plugins::init();
262 292 MainWP_Updates_Overview::init();
263 293 MainWP_Client::init();
264 294 MainWP_Rest_Api_Page::init();
265 - MainWP_Non_MainWP_Actions::instance();
295 + MainWP_Logger::instance();
266 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 +
267 303 if ( defined( 'WP_CLI' ) && WP_CLI ) {
268 304 MainWP_WP_CLI_Command::init();
269 305 }
270 - if ( defined( 'DOING_CRON' ) && DOING_CRON && isset( $_GET['mainwp_run'] ) && 'test' === $_GET['mainwp_run'] ) { // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
271 - add_action( 'init', array( MainWP_System_Cron_Jobs::instance(), 'cron_active' ), PHP_INT_MAX );
272 - }
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 + );
273 314 }
274 315
275 316 /**
276 317 * Method get_dashboard_version()
@@ -283,8 +324,19 @@
283 324 return static::$version;
284 325 }
285 326
286 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 + /**
287 339 * Method load_all_options()
288 340 *
289 341 * Load all wp_options data.
290 342 *
@@ -327,9 +379,8 @@
327 379 'mainwp_enableLegacyBackupFeature',
328 380 'mainwp_maximumInstallUpdateRequests',
329 381 'mainwp_maximumSyncRequests',
330 382 'mainwp_primaryBackup',
331 - 'mainwp_security',
332 383 'mainwp_use_favicon',
333 384 'mainwp_wp_cron',
334 385 'mainwp_timeDailyUpdate',
335 386 'mainwp_frequencyDailyUpdate',
@@ -340,14 +391,11 @@
340 391 'mainwp_disable_update_confirmations',
341 392 'mainwp_settings_show_widgets',
342 393 'mainwp_clients_show_widgets',
343 394 'mainwp_settings_show_manage_sites_columns',
344 - 'mainwp_disableSitesChecking',
395 + 'mainwp_individual_uptime_monitoring_schedule_enabled',
345 396 'mainwp_disableSitesHealthMonitoring',
346 - 'mainwp_frequencySitesChecking',
347 397 'mainwp_sitehealthThreshold',
348 - 'mainwp_settings_notification_emails',
349 - 'mainwp_ignore_HTTP_response_status',
350 398 'mainwp_check_http_response',
351 399 'mainwp_extmenu',
352 400 'mainwp_opensslLibLocation',
353 401 'mainwp_notice_wp_mail_failed',
@@ -354,11 +402,11 @@
354 402 'mainwp_show_language_updates',
355 403 'mainwp_logger_check_daily',
356 404 'mainwp_site_actions_notification_enable',
357 405 'mainwp_update_check_version',
406 + 'mainwp_admin_init_update_data',
358 407 'mainwp_setting_demo_mode_enabled',
359 408 'mainwp_log_wait_lasttime',
360 - 'mainwp_updatescheck_start_last_schedule_timestamp',
361 409 'mainwp_cron_license_deactivated_alert_lasttime',
362 410 'mainwp_updatescheck_is_running',
363 411 'mainwp_automatic_updates_is_running',
364 412 'mainwp_frequency_AutoUpdate',
@@ -363,9 +411,13 @@
363 411 'mainwp_automatic_updates_is_running',
364 412 'mainwp_frequency_AutoUpdate',
365 413 'mainwp_batch_updates_is_running',
366 414 'mainwp_batch_individual_updates_is_running',
367 -
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',
368 420 );
369 421
370 422 $options = apply_filters( 'mainwp_init_load_all_options', $options );
371 423
@@ -408,12 +460,13 @@
408 460 */
409 461 public function localization() {
410 462 $load = apply_filters( 'mainwp_load_text_domain', true );
411 463 if ( $load ) {
412 - 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.
413 465 }
414 466 }
415 467
468 +
416 469 /**
417 470 * Method wp_mail_failed()
418 471 *
419 472 * Check if there has been a wp mail failer.
@@ -500,25 +553,33 @@
500 553 MainWP_System_Cron_Jobs::instance()->cron_updates_check();
501 554 }
502 555
503 556 /**
504 - * Method mainwp_crondeactivatedlicensesalert_action()
557 + * Method mainwp_cron_uptime_monitoring_check_action()
505 558 *
506 - * Run cron activated licenses alert action.
559 + * Run cron uptime monitoring check action.
507 560 */
508 - public function mainwp_crondeactivatedlicensesalert_action() {
509 - 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();
510 563 }
511 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 +
512 575 /**
513 - * Method mainwp_croncheckstatus_action()
576 + * Method mainwp_crondeactivatedlicensesalert_action()
514 577 *
515 - * Run cron check sites status action.
516 - *
517 - * @uses \MainWP\Dashboard\MainWP_System_Cron_Jobs::cron_check_websites_status()
578 + * Run cron activated licenses alert action.
518 579 */
519 - public function mainwp_croncheckstatus_action() {
520 - 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();
521 582 }
522 583
523 584 /**
524 585 * Method mainwp_cronchecksitehealth_action()
@@ -554,45 +615,43 @@
554 615 *
555 616 * @return boolean ture|false.
556 617 */
557 618 public static function is_mainwp_site_page() {
619 + $is_page = false;
558 620 //phpcs:disable WordPress.Security.NonceVerification.Recommended
559 - 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'] ) ) ) {
560 - 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;
561 623 }
562 624 //phpcs:enable
563 - return false;
564 - }
565 625
566 - /**
567 - * Method init()
568 - *
569 - * Instantiate Plugin.
570 - */
571 - public function init() { //phpcs:ignore -- NOSONAR - complex.
572 -
573 626 /**
574 - * MainWP disabled menu items array.
627 + * Hook mainwp_is_mainwp_site_page.
575 628 *
576 - * @global object $_mainwp_disable_menus_items
629 + * @since 5.4.1
577 630 */
578 - global $_mainwp_disable_menus_items;
631 + return apply_filters( 'mainwp_is_mainwp_site_page', $is_page );
632 + }
579 633
580 - $_mainwp_disable_menus_items = apply_filters( 'mainwp_disablemenuitems', $_mainwp_disable_menus_items );
581 634
635 + /**
636 + * Method plugins_loaded()
637 + *
638 + * Load plugin text domain.
639 + */
640 + public function plugins_loaded() { // phpcs:ignore -- NOSONAR - complex.
582 641 /**
583 - * Filter: mainwp_main_menu_disable_menu_items
642 + * Action: mainwp_system_plugins_loaded
584 643 *
585 - * Filters disabled MainWP navigation items.
644 + * Fires after all plugins are loaded.
586 645 *
587 - * @since Unknown
646 + * @since 6.1.0
588 647 */
589 - $_mainwp_disable_menus_items = apply_filters( 'mainwp_main_menu_disable_menu_items', $_mainwp_disable_menus_items );
648 + do_action( 'mainwp_system_plugins_loaded' );
590 649
591 650 if ( ! function_exists( 'MainWP\Dashboard\mainwp_current_user_have_right' ) ) {
592 651
593 652 /**
594 - * Method mainwp_current_user_have_right()
653 + * Method \mainwp_current_user_can()
595 654 *
596 655 * Check permission level by hook mainwp_currentusercan of Team Control extension.
597 656 *
598 657 * @param string $cap_type group or type of capabilities.
@@ -629,9 +688,35 @@
629 688
630 689 return apply_filters( 'mainwp_currentusercan', true, $cap_type, $cap );
631 690 }
632 691 }
692 + }
633 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 +
634 719 MainWP_System_Handler::instance()->handle_settings_post();
635 720 }
636 721
637 722 /**
@@ -684,8 +769,18 @@
684 769 // phpcs:enable
685 770 }
686 771
687 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 + /**
688 783 * Method after_setup_theme()
689 784 *
690 785 * After setup theme hook, to support post thumbnails.
691 786 */
@@ -698,19 +793,15 @@
698 793 * Method hook_admin_update_check()
699 794 */
700 795 public function hook_admin_update_check() {
701 796 $current_ver = $this->check_ver_update;
702 - $saved_ver = get_option( 'mainwp_update_check_version', false );
797 + $saved_ver = get_option( 'mainwp_update_check_version', '' );
703 798
704 - if ( false === $saved_ver ) {
705 - return;
706 - }
707 -
708 799 if ( version_compare( $saved_ver, $current_ver, '=' ) ) {
709 800 return;
710 801 }
711 802
712 - if ( version_compare( $saved_ver, '0.0.4', '<' ) ) {
803 + if ( ! empty( $saved_ver ) && version_compare( $saved_ver, '0.0.4', '<' ) ) {
713 804 $sched = wp_next_scheduled( 'mainwp_cronstats_action' );
714 805 if ( ! empty( $sched ) ) {
715 806 wp_unschedule_event( $sched, 'mainwp_cronstats_action' );
716 807 }
@@ -717,9 +808,9 @@
717 808 global $wpdb;
718 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.
719 810 }
720 811
721 - if ( version_compare( $saved_ver, '0.0.5', '<' ) ) {
812 + if ( ! empty( $saved_ver ) && version_compare( $saved_ver, '0.0.5', '<' ) ) {
722 813 $all_ext = MainWP_Extensions_View::get_available_extensions();
723 814 foreach ( $all_ext as $slug => $info ) {
724 815 $data = MainWP_Api_Manager::instance()->get_activation_info( $slug );
725 816 if ( is_array( $data ) && isset( $data['api_key'] ) ) {
@@ -730,12 +821,73 @@
730 821 }
731 822 update_option( 'mainwp_extensions_all_activation_cached', '' );
732 823 }
733 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 +
734 829 MainWP_Utility::update_option( 'mainwp_update_check_version', $current_ver );
735 830 }
736 831
832 +
737 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 + /**
738 890 * Method admin_init()
739 891 *
740 892 * Do nothing if current user is not an Admin else display the page.
741 893 *
@@ -786,8 +938,9 @@
786 938 MainWP_Post_Plugin_Theme_Handler::instance()->init();
787 939 MainWP_Post_Extension_Handler::instance()->init();
788 940 MainWP_Post_Backup_Handler::instance()->init();
789 941 MainWP_Manage_Sites_Filter_Segment::get_instance()->admin_init();
942 + MainWP_Ui_Manage_Widgets_Layout::get_instance()->admin_init();
790 943
791 944 /**
792 945 * Filter: mainwp_ui_use_wp_calendar
793 946 *
@@ -803,9 +956,14 @@
803 956 $en_params = array( 'jquery-ui-dialog' );
804 957 if ( $use_wp_datepicker ) {
805 958 $en_params[] = 'jquery-ui-datepicker';
806 959 }
960 +
961 + static::$defer_js_handle = array_merge( static::$defer_js_handle, array( 'mainwp' ) );
962 +
807 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 +
808 966 $disable_backup_checking = true; // removed option.
809 967 $mainwpParams = array(
810 968 'image_url' => MAINWP_PLUGIN_URL . 'assets/images/',
811 969 'backup_before_upgrade' => 1 === (int) get_option( 'mainwp_backup_before_upgrade' ),
@@ -816,11 +974,15 @@
816 974 'time_format' => get_option( 'time_format' ),
817 975 'installedBulkSettingsManager' => is_plugin_active( 'mainwp-bulk-settings-manager/mainwp-bulk-settings-manager.php' ) ? 1 : 0,
818 976 'maximumSyncRequests' => ( get_option( 'mainwp_maximumSyncRequests' ) === false ) ? 8 : get_option( 'mainwp_maximumSyncRequests' ),
819 977 'maximumInstallUpdateRequests' => ( get_option( 'mainwp_maximumInstallUpdateRequests' ) === false ) ? 3 : get_option( 'mainwp_maximumInstallUpdateRequests' ),
978 + 'maximumUptimeMonitoringRequests' => (int) get_option( 'mainwp_maximum_uptime_monitoring_requests', 10 ),
820 979 '_wpnonce' => wp_create_nonce( 'mainwp-admin-nonce' ),
980 + 'quickThemeChangeNonce' => wp_create_nonce( 'mainwp_quick_theme_change' ),
821 981 'demoMode' => MainWP_Demo_Handle::is_demo_mode() ? 1 : 0,
822 982 'roll_ui_icon' => MainWP_Updates_Helper::get_roll_icon( '', true ),
983 + 'admin_url_base' => admin_url(),
984 + 'mainwpVersion' => static::$version,
823 985 );
824 986 wp_localize_script( 'mainwp', 'mainwpParams', $mainwpParams );
825 987
826 988 $mainwpTranslations = MainWP_System_View::get_mainwp_translations();
@@ -837,20 +999,22 @@
837 999 wp_enqueue_script( 'thickbox' );
838 1000 wp_enqueue_script( 'user-profile' );
839 1001 wp_enqueue_style( 'thickbox' );
840 1002
841 - $load_gridster = false;
1003 + $load_gridstack = false;
842 1004
843 1005 // phpcs:disable WordPress.Security.NonceVerification
844 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.
845 - $load_gridster = true;
1007 + $load_gridstack = true;
846 1008 }
847 1009
848 - $load_gridster = apply_filters( 'mainwp_enqueue_script_gridster', $load_gridster );
1010 + // compatible filter.
1011 + $load_gridstack = apply_filters( 'mainwp_enqueue_script_gridster', $load_gridstack );
849 1012
850 - if ( $load_gridster ) {
851 - wp_enqueue_script( 'gridster', MAINWP_PLUGIN_URL . 'assets/js/gridster/jquery.dsmorse-gridster.js', array(), $this->current_version, true );
852 - 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 );
853 1017 }
854 1018
855 1019 if ( isset( $_GET['page'] ) && ( 'managesites' === $_GET['page'] || 'MonitoringSites' === $_GET['page'] || 'ManageGroups' === $_GET['page'] ) ) { //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
856 1020 wp_enqueue_script( 'preview', MAINWP_PLUGIN_URL . 'assets/js/preview.js', array(), $this->current_version, true );
@@ -867,9 +1031,34 @@
867 1031 remove_action( 'admin_notices', 'update_nag', 3 );
868 1032 }
869 1033 }
870 1034
1035 +
871 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 + /**
872 1061 * Method hook_plugin_action_links()
873 1062 *
874 1063 * @param string[] $actions An array of plugin action links. By default this can include
875 1064 * 'activate', 'deactivate', and 'delete'. With Multisite active
@@ -951,9 +1140,9 @@
951 1140 $request_uri = isset( $_SERVER['REQUEST_URI'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
952 1141 $_pos = strlen( $request_uri ) - strlen( '/wp-admin/' );
953 1142 if ( ! empty( $request_uri ) && strpos( $request_uri, '/wp-admin/' ) !== false && strpos( $request_uri, '/wp-admin/' ) === $_pos ) {
954 1143 $referer = wp_get_referer();
955 - 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' ) ) {
956 1145 wp_safe_redirect( admin_url( 'admin.php?page=mainwp_tab' ) );
957 1146 die();
958 1147 }
959 1148 }
@@ -1002,14 +1191,15 @@
1002 1191 MainWP_Cache::init_cache( $ca ); // to re-set cache.
1003 1192 }
1004 1193 }
1005 1194
1195 +
1006 1196 /**
1007 1197 * Method admin_enqueue_scripts()
1008 1198 *
1009 1199 * Enqueue all Mainwp Admin Scripts.
1010 1200 */
1011 - public function admin_enqueue_scripts() {
1201 + public function admin_enqueue_scripts() { // phpcs:ignore -- NOSONAR - complex function.
1012 1202
1013 1203 $load_cust_scripts = false;
1014 1204
1015 1205 /**
@@ -1034,21 +1224,20 @@
1034 1224 wp_enqueue_script( 'mainwp-posts', MAINWP_PLUGIN_URL . 'assets/js/mainwp-posts.js', array(), $this->current_version, true );
1035 1225 wp_enqueue_script( 'mainwp-users', MAINWP_PLUGIN_URL . 'assets/js/mainwp-users.js', array(), $this->current_version, true );
1036 1226 wp_enqueue_script( 'mainwp-clients', MAINWP_PLUGIN_URL . 'assets/js/mainwp-clients.js', array(), $this->current_version, true );
1037 1227 wp_enqueue_script( 'mainwp-extensions', MAINWP_PLUGIN_URL . 'assets/js/mainwp-extensions.js', array(), $this->current_version, true );
1038 - wp_enqueue_script( 'mainwp-moment', MAINWP_PLUGIN_URL . 'assets/js/moment/moment.min.js', array(), $this->current_version, true );
1228 + wp_enqueue_script( 'moment' );
1039 1229 wp_enqueue_script( 'fomantic-ui', MAINWP_PLUGIN_URL . 'assets/js/fomantic-ui/fomantic-ui.js', array( 'jquery' ), $this->current_version, false );
1040 1230
1041 - wp_enqueue_script( 'datatables', MAINWP_PLUGIN_URL . 'assets/js/datatables/dataTables.js', array( 'jquery' ), $this->current_version, false );
1042 - 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 );
1043 1233 wp_enqueue_script( 'datatables-select', MAINWP_PLUGIN_URL . 'assets/js/datatables/dataTables.select.min.js', array( 'datatables' ), $this->current_version, false );
1044 - 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 );
1045 1235
1046 - wp_enqueue_script( 'hamburger', MAINWP_PLUGIN_URL . 'assets/js/hamburger/hamburger.js', array( 'jquery' ), $this->current_version, true );
1047 - 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 );
1048 1237
1049 - wp_enqueue_script( 'mainwp-clipboard', MAINWP_PLUGIN_URL . 'assets/js/clipboard/clipboard.min.js', array( 'jquery' ), $this->current_version, true );
1050 - 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 );
1051 1240
1052 1241 if ( isset( $_GET['page'] ) && 'ManageGroups' === $_GET['page'] ) { // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1053 1242 wp_enqueue_script( 'mainwp-groups', MAINWP_PLUGIN_URL . 'assets/js/mainwp-groups.js', array(), $this->current_version, true );
1054 1243 }
@@ -1055,9 +1244,9 @@
1055 1244 $enqueue_scripts = apply_filters( 'mainwp_admin_enqueue_scripts', array() );
1056 1245 if ( is_array( $enqueue_scripts ) && ! empty( $enqueue_scripts['apexcharts'] ) ) {
1057 1246 wp_enqueue_script(
1058 1247 'mainwp-apexcharts',
1059 - MAINWP_PLUGIN_URL . 'assets/js/apexcharts/apexcharts.js',
1248 + MAINWP_PLUGIN_URL . 'assets/js/apexcharts/apexcharts.min.js',
1060 1249 array(
1061 1250 'jquery',
1062 1251 'mainwp',
1063 1252 ),
@@ -1063,24 +1252,633 @@
1063 1252 ),
1064 1253 $this->current_version,
1065 1254 true
1066 1255 );
1256 + static::$defer_js_handle[] = 'mainwp-apexcharts';
1067 1257 }
1068 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 +
1069 1262 }
1070 1263
1071 1264 if ( $load_cust_scripts ) {
1265 + static::$defer_js_handle[] = 'fomantic-ui';
1072 1266 wp_enqueue_script( 'fomantic-ui', MAINWP_PLUGIN_URL . 'assets/js/fomantic-ui/fomantic-ui.js', array( 'jquery' ), $this->current_version, true );
1073 1267 }
1074 1268
1075 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 + );
1076 1277 wp_enqueue_script( 'mainwp-js-popup', MAINWP_PLUGIN_URL . 'assets/js/mainwp-popup.js', array(), $this->current_version, true );
1077 1278 // to support extension uploader.
1078 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.
1079 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();
1080 1294 }
1081 1295
1082 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 + /**
1083 1881 * Method admin_enqueue_scripts_fix_conflict()
1084 1882 *
1085 1883 * Enqueue Admin Scripts fix conflict.
1086 1884 */
@@ -1121,14 +1919,12 @@
1121 1919 wp_enqueue_style( 'mainwp-fonts', MAINWP_PLUGIN_URL . 'assets/css/mainwp-fonts.css', array(), $this->current_version );
1122 1920 wp_enqueue_style( 'fomantic-ui', MAINWP_PLUGIN_URL . 'assets/js/fomantic-ui/fomantic-ui.css', array(), $this->current_version );
1123 1921 wp_enqueue_style( 'mainwp-fomantic', MAINWP_PLUGIN_URL . 'assets/css/mainwp-fomantic.css', array(), $this->current_version );
1124 1922
1125 - wp_enqueue_style( 'datatables', MAINWP_PLUGIN_URL . 'assets/js/datatables/dataTables.dataTables.css', array(), $this->current_version );
1126 - 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 );
1127 1925 wp_enqueue_style( 'datatables-select', MAINWP_PLUGIN_URL . 'assets/js/datatables/select.semanticui.min.css', array(), $this->current_version );
1128 - wp_enqueue_style( 'datatables-add-ons', MAINWP_PLUGIN_URL . 'assets/js/datatables/datatables.min.css', array(), $this->current_version );
1129 -
1130 - 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 );
1131 1927 // to fix conflict layout.
1132 1928 wp_enqueue_style( 'jquery-ui-style', MAINWP_PLUGIN_URL . 'assets/css/1.11.1/jquery-ui.min.css', array(), '1.11.1' );
1133 1929
1134 1930 // load custom MainWP theme.
@@ -1139,10 +1935,14 @@
1139 1935 } elseif ( 'wpadmin' === $selected_theme ) {
1140 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 );
1141 1937 } elseif ( 'minimalistic' === $selected_theme ) {
1142 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 );
1143 1941 } elseif ( 'default' === $selected_theme ) {
1144 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 );
1145 1945 } else {
1146 1946 $dirs = MainWP_Settings::get_instance()->get_custom_theme_folder();
1147 1947 $custom_theme_url = $dirs[1];
1148 1948 wp_enqueue_style( 'mainwp-custom-dashboard-theme', $custom_theme_url . $selected_theme, array(), $this->current_version );
@@ -1250,9 +2050,9 @@
1250 2050 }
1251 2051 } elseif ( 'UpdatesManage' === $_GET['page'] || 'mainwp_tab' === $_GET['page'] ) { // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1252 2052 $staging_enabled = is_plugin_active( 'mainwp-staging-extension/mainwp-staging-extension.php' ) ? true : false;
1253 2053 if ( $staging_enabled ) {
1254 - $staging_view = MainWP_System_Utility::get_staging_options_sites_view_for_current_users();
2054 + $staging_view = MainWP_System_Utility::get_select_staging_view_sites();
1255 2055 if ( 'staging' === $staging_view ) {
1256 2056 $is_staging = 'yes';
1257 2057 }
1258 2058 }
@@ -1268,10 +2068,8 @@
1268 2068
1269 2069 MainWP_System_View::admin_footer();
1270 2070 MainWP_System_View::render_plugins_install_check();
1271 2071
1272 - MainWP_Menu::init_sub_pages();
1273 -
1274 2072 /**
1275 2073 * MainWP disabled menu items array.
1276 2074 *
1277 2075 * @global object
@@ -1312,8 +2110,17 @@
1312 2110 * Deactivate MainWP.
1313 2111 */
1314 2112 public function deactivation() {
1315 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 + }
1316 2123 }
1317 2124
1318 2125 /**
1319 2126 * Method update_install()
@@ -1374,6 +2181,57 @@
1374 2181 * Get MainWP Plugin Slug.
1375 2182 */
1376 2183 public function get_plugin_slug() {
1377 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;
1378 2236 }
1379 2237 }