From 6c5cbb8bba2edd300fdd3744131c4f94ba38d814 Mon Sep 17 00:00:00 2001 From: David Stone Date: Tue, 14 Apr 2026 09:41:28 -0600 Subject: [PATCH] feat: add Network Activate button in setup wizard for non-network-active plugin When Ultimate Multisite is not network active, the Pre-install Checks step now shows a 'Network Activate' button instead of only a 'Read More' link. - Add ajax_network_activate() AJAX handler in Setup_Wizard_Admin_Page to perform network activation of the plugin - Update renders_requirements_table() to compute can_activate flag and nonce, passing them to the wp-ultimo plugin requirement item - Update requirements_table.php view: show 'Network Activate' button when can_activate is true; on AJAX failure, reveal the 'Read More' fallback link; update bottom error message to reference the button - Add inline JS (jQuery) to call the AJAX handler and reload on success, or surface the fallback link on failure - Add tests for the new AJAX action hook registration and permission guard Resolves #836 --- .../class-setup-wizard-admin-page.php | 54 ++++++++++- .../Setup_Wizard_Admin_Page_Test.php | 21 ++++ views/wizards/setup/requirements_table.php | 97 ++++++++++++++++++- 3 files changed, 163 insertions(+), 9 deletions(-) diff --git a/inc/admin-pages/class-setup-wizard-admin-page.php b/inc/admin-pages/class-setup-wizard-admin-page.php index b7d6d5acc..f17eaa16b 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 dd46a7327..dc41732ca 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 97fb30a59..363ea7c79 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'); ?> + + + + +
+ +