From e4f5422d8cc25c0d94639b89f80aecd523f7dd1b Mon Sep 17 00:00:00 2001 From: Rashed Hossain Date: Wed, 19 Aug 2026 15:12:50 +0600 Subject: [PATCH] Plugins: Show "Activate" after updating an inactive plugin from the Add Plugins screen. When updating an inactive plugin from the Add Plugins screen (Plugins > Add New), the button remained in the disabled "Updated!" state instead of transitioning to "Activate", requiring users to navigate to Installed Plugins to activate it. This updates `wp_ajax_update_plugin()` to return `activateUrl` for inactive plugins that the current user has permission to activate, matching `wp_ajax_install_plugin()`. It also updates `wp.updates.updatePluginSuccess` to check plugin dependencies and transform the button to an "Activate" link, and updates `checkPluginDependenciesSuccess` / `checkPluginDependenciesError` to handle `.update-now` buttons alongside `.install-now`. Fixes #65909. --- src/js/_enqueues/wp/updates.js | 22 +++++++++++++++------- src/wp-admin/includes/ajax-actions.php | 20 ++++++++++++++++++++ 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/src/js/_enqueues/wp/updates.js b/src/js/_enqueues/wp/updates.js index ef4b47e66093e..476bb7924b460 100644 --- a/src/js/_enqueues/wp/updates.js +++ b/src/js/_enqueues/wp/updates.js @@ -611,6 +611,14 @@ } $document.trigger( 'wp-plugin-update-success', response ); + + if ( response.activateUrl ) { + setTimeout( function() { + wp.updates.checkPluginDependencies( { + slug: response.slug + } ); + }, 1000 ); + } }; /** @@ -953,12 +961,12 @@ * @param {string} response.activateUrl URL to activate the just checked plugin. */ wp.updates.checkPluginDependenciesSuccess = function( response ) { - var $message = $( '.plugin-card-' + response.slug + ', #plugin-information-footer' ).find( '.install-now' ), + var $message = $( '.plugin-card-' + response.slug + ', #plugin-information-footer' ).find( '.install-now, .update-now' ), buttonText, ariaLabel; - // Transform the 'Install' button into an 'Activate' button. + // Transform the 'Install' or 'Update' button into an 'Activate' button. $message - .removeClass( 'install-now installed button-disabled updated-message' ) + .removeClass( 'install-now update-now installed button-disabled updated-message' ) .addClass( 'activate-now button-primary' ) .attr( 'href', response.activateUrl ); @@ -997,7 +1005,7 @@ { status: 'dependencies-check-success', slug: response.slug, - removeClasses: 'install-now installed button-disabled updated-message', + removeClasses: 'install-now update-now installed button-disabled updated-message', addClasses: 'activate-now button-primary', text: buttonText, ariaLabel: ariaLabel, @@ -1021,7 +1029,7 @@ * @param {string} response.errorMessage The error that occurred. */ wp.updates.checkPluginDependenciesError = function( response ) { - var $message = $( '.plugin-card-' + response.slug + ', #plugin-information-footer' ).find( '.install-now' ), + var $message = $( '.plugin-card-' + response.slug + ', #plugin-information-footer' ).find( '.install-now, .update-now' ), buttonText = _x( 'Activate', 'plugin' ), ariaLabel = sprintf( /* translators: 1: Plugin name, 2. The reason the plugin cannot be activated. */ @@ -1045,7 +1053,7 @@ $document.trigger( 'wp-check-plugin-dependencies-error', response ); $message - .removeClass( 'install-now installed updated-message' ) + .removeClass( 'install-now update-now installed updated-message' ) .addClass( 'activate-now button-primary' ) .attr( 'aria-label', ariaLabel ) .text( buttonText ); @@ -1055,7 +1063,7 @@ { status: 'dependencies-check-failed', slug: response.slug, - removeClasses: 'install-now installed updated-message', + removeClasses: 'install-now update-now installed updated-message', addClasses: 'activate-now button-primary', text: buttonText, ariaLabel: ariaLabel diff --git a/src/wp-admin/includes/ajax-actions.php b/src/wp-admin/includes/ajax-actions.php index 747bcc75e53eb..723c08aebb0e8 100644 --- a/src/wp-admin/includes/ajax-actions.php +++ b/src/wp-admin/includes/ajax-actions.php @@ -4721,6 +4721,26 @@ function wp_ajax_update_plugin() { $status['newVersion'] = sprintf( __( 'Version %s' ), $plugin_data['Version'] ); } + $pagenow = isset( $_POST['pagenow'] ) ? sanitize_key( $_POST['pagenow'] ) : ''; + + // If update request is coming from import page, do not return network activation link. + $plugins_url = ( 'import' === $pagenow ) ? admin_url( 'plugins.php' ) : network_admin_url( 'plugins.php' ); + + if ( current_user_can( 'activate_plugin', $plugin ) && is_plugin_inactive( $plugin ) ) { + $status['activateUrl'] = add_query_arg( + array( + '_wpnonce' => wp_create_nonce( 'activate-plugin_' . $plugin ), + 'action' => 'activate', + 'plugin' => $plugin, + ), + $plugins_url + ); + + if ( is_multisite() && current_user_can( 'manage_network_plugins' ) && 'import' !== $pagenow ) { + $status['activateUrl'] = add_query_arg( array( 'networkwide' => 1 ), $status['activateUrl'] ); + } + } + wp_send_json_success( $status ); } elseif ( false === $result ) { global $wp_filesystem;