diff --git a/inc/admin-pages/class-setup-wizard-admin-page.php b/inc/admin-pages/class-setup-wizard-admin-page.php index b7d6d5ac..f17eaa16 100644 --- a/inc/admin-pages/class-setup-wizard-admin-page.php +++ b/inc/admin-pages/class-setup-wizard-admin-page.php @@ -143,6 +143,45 @@ public function __construct() { add_filter('wu_handle_ajax_installers', [Migrator::get_instance(), 'handle'], 10, 3); add_action('admin_init', [$this, 'alert_incomplete_installation']); + + /* + * Handle network activation of Ultimate Multisite via AJAX. + */ + add_action('wp_ajax_wu_setup_network_activate', [$this, 'ajax_network_activate']); + } + + /** + * Handles the AJAX request to network-activate Ultimate Multisite. + * + * Attempts to network-activate the plugin, returning a JSON response. + * On success the caller should reload the page so the checks refresh. + * + * @since 2.3.0 + * @return void + */ + public function ajax_network_activate(): void { + + check_ajax_referer('wu_setup_network_activate', 'nonce'); + + if ( ! current_user_can('manage_network')) { + wp_send_json_error(new \WP_Error('not-allowed', __('Permission denied.', 'ultimate-multisite'))); + + exit; + } + + if ( ! function_exists('activate_plugin')) { + require_once ABSPATH . 'wp-admin/includes/plugin.php'; + } + + $result = activate_plugin(WP_ULTIMO_PLUGIN_BASENAME, '', true); + + if (is_wp_error($result)) { + wp_send_json_error($result); + + exit; + } + + wp_send_json_success(); } /** @@ -628,6 +667,10 @@ public function renders_requirements_table() { ], ]; + $is_network_active = Requirements::is_network_active(); + + $can_network_activate = ! $is_network_active && current_user_can('manage_network'); + $plugin_requirements = [ 'multisite' => [ 'name' => __('WordPress Multisite', 'ultimate-multisite'), @@ -636,10 +679,12 @@ public function renders_requirements_table() { 'pass_requirements' => is_multisite(), ], 'wp-ultimo' => [ - 'name' => __('Ultimate Multisite', 'ultimate-multisite'), - 'help' => wu_get_documentation_url('wp-ultimo-requirements'), - 'condition' => apply_filters('wp_ultimo_skip_network_active_check', false) ? __('Bypassed via filter', 'ultimate-multisite') : __('Network Activated', 'ultimate-multisite'), - 'pass_requirements' => Requirements::is_network_active(), + 'name' => __('Ultimate Multisite', 'ultimate-multisite'), + 'help' => wu_get_documentation_url('wp-ultimo-requirements'), + 'condition' => apply_filters('wp_ultimo_skip_network_active_check', false) ? __('Bypassed via filter', 'ultimate-multisite') : __('Network Activated', 'ultimate-multisite'), + 'pass_requirements' => $is_network_active, + 'can_activate' => $can_network_activate, + 'network_activate_nonce' => $can_network_activate ? wp_create_nonce('wu_setup_network_activate') : '', ], 'wp-cron' => [ 'name' => __('WordPress Cron', 'ultimate-multisite'), @@ -654,6 +699,7 @@ public function renders_requirements_table() { [ 'requirements' => $requirements, 'plugin_requirements' => $plugin_requirements, + 'has_activate_button' => $can_network_activate, ] ); } diff --git a/tests/WP_Ultimo/Admin_Pages/Setup_Wizard_Admin_Page_Test.php b/tests/WP_Ultimo/Admin_Pages/Setup_Wizard_Admin_Page_Test.php index dd46a732..dc41732c 100644 --- a/tests/WP_Ultimo/Admin_Pages/Setup_Wizard_Admin_Page_Test.php +++ b/tests/WP_Ultimo/Admin_Pages/Setup_Wizard_Admin_Page_Test.php @@ -41,6 +41,7 @@ protected function tearDown(): void { $_REQUEST['installer'], $_REQUEST['dry-run'], $_REQUEST['step'], + $_REQUEST['nonce'], $_GET['action'], $_GET['nonce'], $_GET['_wpnonce'] @@ -443,4 +444,24 @@ public function test_constructor_registers_alert_incomplete_installation(): void has_action('admin_init', [$this->page, 'alert_incomplete_installation']) ); } + + public function test_constructor_registers_network_activate_ajax_action(): void { + $this->assertGreaterThan( + 0, + has_action('wp_ajax_wu_setup_network_activate', [$this->page, 'ajax_network_activate']) + ); + } + + // ------------------------------------------------------------------------- + // ajax_network_activate() — permission guard + // ------------------------------------------------------------------------- + + public function test_ajax_network_activate_sends_json_error_without_permission(): void { + // Provide a valid nonce so the nonce check passes, isolating the permission check. + $_REQUEST['nonce'] = wp_create_nonce('wu_setup_network_activate'); + wp_set_current_user(0); + $this->expectException(\WPAjaxDieStopException::class); + $this->page->ajax_network_activate(); + } + } diff --git a/views/wizards/setup/requirements_table.php b/views/wizards/setup/requirements_table.php index 97fb30a5..363ea7c7 100644 --- a/views/wizards/setup/requirements_table.php +++ b/views/wizards/setup/requirements_table.php @@ -71,10 +71,38 @@ - - - - + + +
+ + + + +
+ + + + + + + + + @@ -88,9 +116,68 @@
- Read More links on each item to see what steps you need to take to bring your environment up to the Ultimate Multisite current requirements.', 'ultimate-multisite'); ?> + + + + +
+ +