--- a/wp/wp-admin/js/updates.js Thu Sep 29 08:06:27 2022 +0200
+++ b/wp/wp-admin/js/updates.js Fri Sep 05 18:40:08 2025 +0200
@@ -5,7 +5,7 @@
* @output wp-admin/js/updates.js
*/
-/* global pagenow */
+/* global pagenow, _wpThemeSettings */
/**
* @param {jQuery} $ jQuery object.
@@ -414,6 +414,31 @@
};
/**
+ * Sends a message from a modal to the main screen to update buttons in plugin cards.
+ *
+ * @since 6.5.0
+ *
+ * @param {Object} data An object of data to use for the button.
+ * @param {string} data.slug The plugin's slug.
+ * @param {string} data.text The text to use for the button.
+ * @param {string} data.ariaLabel The value for the button's aria-label attribute. An empty string removes the attribute.
+ * @param {string=} data.status Optional. An identifier for the status.
+ * @param {string=} data.removeClasses Optional. A space-separated list of classes to remove from the button.
+ * @param {string=} data.addClasses Optional. A space-separated list of classes to add to the button.
+ * @param {string=} data.href Optional. The button's URL.
+ * @param {string=} data.pluginName Optional. The plugin's name.
+ * @param {string=} data.plugin Optional. The plugin file, relative to the plugins directory.
+ */
+ wp.updates.setCardButtonStatus = function( data ) {
+ var target = window.parent === window ? null : window.parent;
+
+ $.support.postMessage = !! window.postMessage;
+ if ( false !== $.support.postMessage && null !== target && -1 === window.parent.location.pathname.indexOf( 'index.php' ) ) {
+ target.postMessage( JSON.stringify( data ), window.location.origin );
+ }
+ };
+
+ /**
* Decrements the update counts throughout the various menus.
*
* This includes the toolbar, the "Updates" menu item and the menu items
@@ -452,7 +477,9 @@
*/
wp.updates.updatePlugin = function( args ) {
var $updateRow, $card, $message, message,
- $adminBarUpdates = $( '#wp-admin-bar-updates' );
+ $adminBarUpdates = $( '#wp-admin-bar-updates' ),
+ buttonText = __( 'Updating...' ),
+ isPluginInstall = 'plugin-install' === pagenow || 'plugin-install-network' === pagenow;
args = _.extend( {
success: wp.updates.updatePluginSuccess,
@@ -467,8 +494,8 @@
_x( 'Updating %s...', 'plugin' ),
$updateRow.find( '.plugin-title strong' ).text()
);
- } else if ( 'plugin-install' === pagenow || 'plugin-install-network' === pagenow ) {
- $card = $( '.plugin-card-' + args.slug );
+ } else if ( isPluginInstall ) {
+ $card = $( '.plugin-card-' + args.slug + ', #plugin-information-footer' );
$message = $card.find( '.update-now' ).addClass( 'updating-message' );
message = sprintf(
/* translators: %s: Plugin name and version. */
@@ -488,10 +515,22 @@
$message
.attr( 'aria-label', message )
- .text( __( 'Updating...' ) );
+ .text( buttonText );
$document.trigger( 'wp-plugin-updating', args );
+ if ( isPluginInstall && 'plugin-information-footer' === $card.attr( 'id' ) ) {
+ wp.updates.setCardButtonStatus(
+ {
+ status: 'updating-plugin',
+ slug: args.slug,
+ addClasses: 'updating-message',
+ text: buttonText,
+ ariaLabel: message
+ }
+ );
+ }
+
return wp.updates.ajax( 'update-plugin', args );
};
@@ -511,11 +550,17 @@
*/
wp.updates.updatePluginSuccess = function( response ) {
var $pluginRow, $updateMessage, newText,
- $adminBarUpdates = $( '#wp-admin-bar-updates' );
+ $adminBarUpdates = $( '#wp-admin-bar-updates' ),
+ buttonText = _x( 'Updated!', 'plugin' ),
+ ariaLabel = sprintf(
+ /* translators: %s: Plugin name and version. */
+ _x( '%s updated!', 'plugin' ),
+ response.pluginName
+ );
if ( 'plugins' === pagenow || 'plugins-network' === pagenow ) {
$pluginRow = $( 'tr[data-plugin="' + response.plugin + '"]' )
- .removeClass( 'update' )
+ .removeClass( 'update is-enqueued' )
.addClass( 'updated' );
$updateMessage = $pluginRow.find( '.update-message' )
.removeClass( 'updating-message notice-warning' )
@@ -528,7 +573,7 @@
// Clear the "time to next auto-update" text.
$pluginRow.find( '.auto-update-time' ).empty();
} else if ( 'plugin-install' === pagenow || 'plugin-install-network' === pagenow ) {
- $updateMessage = $( '.plugin-card-' + response.slug ).find( '.update-now' )
+ $updateMessage = $( '.plugin-card-' + response.slug + ', #plugin-information-footer' ).find( '.update-now' )
.removeClass( 'updating-message' )
.addClass( 'button-disabled updated-message' );
}
@@ -536,19 +581,25 @@
$adminBarUpdates.removeClass( 'spin' );
$updateMessage
- .attr(
- 'aria-label',
- sprintf(
- /* translators: %s: Plugin name and version. */
- _x( '%s updated!', 'plugin' ),
- response.pluginName
- )
- )
- .text( _x( 'Updated!', 'plugin' ) );
+ .attr( 'aria-label', ariaLabel )
+ .text( buttonText );
wp.a11y.speak( __( 'Update completed successfully.' ) );
- wp.updates.decrementCount( 'plugin' );
+ if ( 'plugin_install_from_iframe' !== $updateMessage.attr( 'id' ) ) {
+ wp.updates.decrementCount( 'plugin' );
+ } else {
+ wp.updates.setCardButtonStatus(
+ {
+ status: 'updated-plugin',
+ slug: response.slug,
+ removeClasses: 'updating-message',
+ addClasses: 'button-disabled updated-message',
+ text: buttonText,
+ ariaLabel: ariaLabel
+ }
+ );
+ }
$document.trigger( 'wp-plugin-update-success', response );
};
@@ -567,7 +618,7 @@
* @param {string} response.errorMessage The error that occurred.
*/
wp.updates.updatePluginError = function( response ) {
- var $card, $message, errorMessage,
+ var $pluginRow, $card, $message, errorMessage, buttonText, ariaLabel,
$adminBarUpdates = $( '#wp-admin-bar-updates' );
if ( ! wp.updates.isValidResponse( response, 'update' ) ) {
@@ -585,6 +636,8 @@
);
if ( 'plugins' === pagenow || 'plugins-network' === pagenow ) {
+ $pluginRow = $( 'tr[data-plugin="' + response.plugin + '"]' ).removeClass( 'is-enqueued' );
+
if ( response.plugin ) {
$message = $( 'tr[data-plugin="' + response.plugin + '"]' ).find( '.update-message' );
} else {
@@ -606,28 +659,32 @@
$message.find( 'p' ).removeAttr( 'aria-label' );
}
} else if ( 'plugin-install' === pagenow || 'plugin-install-network' === pagenow ) {
- $card = $( '.plugin-card-' + response.slug )
- .addClass( 'plugin-card-update-failed' )
+ buttonText = __( 'Update failed.' );
+
+ $card = $( '.plugin-card-' + response.slug + ', #plugin-information-footer' )
.append( wp.updates.adminNotice( {
className: 'update-message notice-error notice-alt is-dismissible',
message: errorMessage
} ) );
+ if ( $card.hasClass( 'plugin-card-' + response.slug ) ) {
+ $card.addClass( 'plugin-card-update-failed' );
+ }
+
$card.find( '.update-now' )
- .text( __( 'Update failed.' ) )
+ .text( buttonText )
.removeClass( 'updating-message' );
if ( response.pluginName ) {
- $card.find( '.update-now' )
- .attr(
- 'aria-label',
- sprintf(
- /* translators: %s: Plugin name and version. */
- _x( '%s update failed.', 'plugin' ),
- response.pluginName
- )
- );
+ ariaLabel = sprintf(
+ /* translators: %s: Plugin name and version. */
+ _x( '%s update failed.', 'plugin' ),
+ response.pluginName
+ );
+
+ $card.find( '.update-now' ).attr( 'aria-label', ariaLabel );
} else {
+ ariaLabel = '';
$card.find( '.update-now' ).removeAttr( 'aria-label' );
}
@@ -650,6 +707,18 @@
wp.a11y.speak( errorMessage, 'assertive' );
+ if ( 'plugin-information-footer' === $card.attr('id' ) ) {
+ wp.updates.setCardButtonStatus(
+ {
+ status: 'plugin-update-failed',
+ slug: response.slug,
+ removeClasses: 'updating-message',
+ text: buttonText,
+ ariaLabel: ariaLabel
+ }
+ );
+ }
+
$document.trigger( 'wp-plugin-update-error', response );
};
@@ -666,8 +735,10 @@
* decorated with an abort() method.
*/
wp.updates.installPlugin = function( args ) {
- var $card = $( '.plugin-card-' + args.slug ),
- $message = $card.find( '.install-now' );
+ var $card = $( '.plugin-card-' + args.slug + ', #plugin-information-footer' ),
+ $message = $card.find( '.install-now' ),
+ buttonText = __( 'Installing...' ),
+ ariaLabel;
args = _.extend( {
success: wp.updates.installPluginSuccess,
@@ -682,17 +753,16 @@
$message.data( 'originaltext', $message.html() );
}
+ ariaLabel = sprintf(
+ /* translators: %s: Plugin name and version. */
+ _x( 'Installing %s...', 'plugin' ),
+ $message.data( 'name' )
+ );
+
$message
.addClass( 'updating-message' )
- .attr(
- 'aria-label',
- sprintf(
- /* translators: %s: Plugin name and version. */
- _x( 'Installing %s...', 'plugin' ),
- $message.data( 'name' )
- )
- )
- .text( __( 'Installing...' ) );
+ .attr( 'aria-label', ariaLabel )
+ .text( buttonText );
wp.a11y.speak( __( 'Installing... please wait.' ) );
@@ -701,6 +771,18 @@
$document.trigger( 'wp-plugin-installing', args );
+ if ( 'plugin-information-footer' === $message.parent().attr( 'id' ) ) {
+ wp.updates.setCardButtonStatus(
+ {
+ status: 'installing-plugin',
+ slug: args.slug,
+ addClasses: 'updating-message',
+ text: buttonText,
+ ariaLabel: ariaLabel
+ }
+ );
+ }
+
return wp.updates.ajax( 'install-plugin', args );
};
@@ -715,20 +797,19 @@
* @param {string} response.activateUrl URL to activate the just installed plugin.
*/
wp.updates.installPluginSuccess = function( response ) {
- var $message = $( '.plugin-card-' + response.slug ).find( '.install-now' );
+ var $message = $( '.plugin-card-' + response.slug + ', #plugin-information-footer' ).find( '.install-now' ),
+ buttonText = _x( 'Installed!', 'plugin' ),
+ ariaLabel = sprintf(
+ /* translators: %s: Plugin name and version. */
+ _x( '%s installed!', 'plugin' ),
+ response.pluginName
+ );
$message
.removeClass( 'updating-message' )
.addClass( 'updated-message installed button-disabled' )
- .attr(
- 'aria-label',
- sprintf(
- /* translators: %s: Plugin name and version. */
- _x( '%s installed!', 'plugin' ),
- response.pluginName
- )
- )
- .text( _x( 'Installed!', 'plugin' ) );
+ .attr( 'aria-label', ariaLabel )
+ .text( buttonText );
wp.a11y.speak( __( 'Installation completed successfully.' ) );
@@ -736,36 +817,23 @@
if ( response.activateUrl ) {
setTimeout( function() {
-
- // Transform the 'Install' button into an 'Activate' button.
- $message.removeClass( 'install-now installed button-disabled updated-message' )
- .addClass( 'activate-now button-primary' )
- .attr( 'href', response.activateUrl );
-
- if ( 'plugins-network' === pagenow ) {
- $message
- .attr(
- 'aria-label',
- sprintf(
- /* translators: %s: Plugin name. */
- _x( 'Network Activate %s', 'plugin' ),
- response.pluginName
- )
- )
- .text( __( 'Network Activate' ) );
- } else {
- $message
- .attr(
- 'aria-label',
- sprintf(
- /* translators: %s: Plugin name. */
- _x( 'Activate %s', 'plugin' ),
- response.pluginName
- )
- )
- .text( __( 'Activate' ) );
+ wp.updates.checkPluginDependencies( {
+ slug: response.slug
+ } );
+ }, 1000 );
+ }
+
+ if ( 'plugin-information-footer' === $message.parent().attr( 'id' ) ) {
+ wp.updates.setCardButtonStatus(
+ {
+ status: 'installed-plugin',
+ slug: response.slug,
+ removeClasses: 'updating-message',
+ addClasses: 'updated-message installed button-disabled',
+ text: buttonText,
+ ariaLabel: ariaLabel
}
- }, 1000 );
+ );
}
};
@@ -781,8 +849,14 @@
* @param {string} response.errorMessage The error that occurred.
*/
wp.updates.installPluginError = function( response ) {
- var $card = $( '.plugin-card-' + response.slug ),
+ var $card = $( '.plugin-card-' + response.slug + ', #plugin-information-footer' ),
$button = $card.find( '.install-now' ),
+ buttonText = __( 'Installation failed.' ),
+ ariaLabel = sprintf(
+ /* translators: %s: Plugin name and version. */
+ _x( '%s installation failed', 'plugin' ),
+ $button.data( 'name' )
+ ),
errorMessage;
if ( ! wp.updates.isValidResponse( response, 'install' ) ) {
@@ -801,7 +875,7 @@
$card
.addClass( 'plugin-card-update-failed' )
- .append( '<div class="notice notice-error notice-alt is-dismissible"><p>' + errorMessage + '</p></div>' );
+ .append( '<div class="notice notice-error notice-alt is-dismissible" role="alert"><p>' + errorMessage + '</p></div>' );
$card.on( 'click', '.notice.is-dismissible .notice-dismiss', function() {
@@ -815,19 +889,332 @@
$button
.removeClass( 'updating-message' ).addClass( 'button-disabled' )
- .attr(
- 'aria-label',
- sprintf(
- /* translators: %s: Plugin name and version. */
- _x( '%s installation failed', 'plugin' ),
- $button.data( 'name' )
- )
- )
- .text( __( 'Installation failed.' ) );
+ .attr( 'aria-label', ariaLabel )
+ .text( buttonText );
+
+ wp.a11y.speak( errorMessage, 'assertive' );
+
+ wp.updates.setCardButtonStatus(
+ {
+ status: 'plugin-install-failed',
+ slug: response.slug,
+ removeClasses: 'updating-message',
+ addClasses: 'button-disabled',
+ text: buttonText,
+ ariaLabel: ariaLabel
+ }
+ );
+
+ $document.trigger( 'wp-plugin-install-error', response );
+ };
+
+ /**
+ * Sends an Ajax request to the server to check a plugin's dependencies.
+ *
+ * @since 6.5.0
+ *
+ * @param {Object} args Arguments.
+ * @param {string} args.slug Plugin identifier in the WordPress.org Plugin repository.
+ * @param {checkPluginDependenciesSuccess=} args.success Optional. Success callback. Default: wp.updates.checkPluginDependenciesSuccess
+ * @param {checkPluginDependenciesError=} args.error Optional. Error callback. Default: wp.updates.checkPluginDependenciesError
+ * @return {$.promise} A jQuery promise that represents the request,
+ * decorated with an abort() method.
+ */
+ wp.updates.checkPluginDependencies = function( args ) {
+ args = _.extend( {
+ success: wp.updates.checkPluginDependenciesSuccess,
+ error: wp.updates.checkPluginDependenciesError
+ }, args );
+
+ wp.a11y.speak( __( 'Checking plugin dependencies... please wait.' ) );
+ $document.trigger( 'wp-checking-plugin-dependencies', args );
+
+ return wp.updates.ajax( 'check_plugin_dependencies', args );
+ };
+
+ /**
+ * Updates the UI appropriately after a successful plugin dependencies check.
+ *
+ * @since 6.5.0
+ *
+ * @param {Object} response Response from the server.
+ * @param {string} response.slug Slug of the checked plugin.
+ * @param {string} response.pluginName Name of the checked plugin.
+ * @param {string} response.plugin The plugin file, relative to the plugins directory.
+ * @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' ),
+ buttonText, ariaLabel;
+
+ // Transform the 'Install' button into an 'Activate' button.
+ $message
+ .removeClass( 'install-now installed button-disabled updated-message' )
+ .addClass( 'activate-now button-primary' )
+ .attr( 'href', response.activateUrl );
+
+ wp.a11y.speak( __( 'Plugin dependencies check completed successfully.' ) );
+ $document.trigger( 'wp-check-plugin-dependencies-success', response );
+
+ if ( 'plugins-network' === pagenow ) {
+ buttonText = _x( 'Network Activate', 'plugin' );
+ ariaLabel = sprintf(
+ /* translators: %s: Plugin name. */
+ _x( 'Network Activate %s', 'plugin' ),
+ response.pluginName
+ );
+
+ $message
+ .attr( 'aria-label', ariaLabel )
+ .text( buttonText );
+ } else {
+ buttonText = _x( 'Activate', 'plugin' );
+ ariaLabel = sprintf(
+ /* translators: %s: Plugin name. */
+ _x( 'Activate %s', 'plugin' ),
+ response.pluginName
+ );
+
+ $message
+ .attr( 'aria-label', ariaLabel )
+ .attr( 'data-name', response.pluginName )
+ .attr( 'data-slug', response.slug )
+ .attr( 'data-plugin', response.plugin )
+ .text( buttonText );
+ }
+
+ if ( 'plugin-information-footer' === $message.parent().attr( 'id' ) ) {
+ wp.updates.setCardButtonStatus(
+ {
+ status: 'dependencies-check-success',
+ slug: response.slug,
+ removeClasses: 'install-now installed button-disabled updated-message',
+ addClasses: 'activate-now button-primary',
+ text: buttonText,
+ ariaLabel: ariaLabel,
+ pluginName: response.pluginName,
+ plugin: response.plugin,
+ href: response.activateUrl
+ }
+ );
+ }
+ };
+
+ /**
+ * Updates the UI appropriately after a failed plugin dependencies check.
+ *
+ * @since 6.5.0
+ *
+ * @param {Object} response Response from the server.
+ * @param {string} response.slug Slug of the plugin to be checked.
+ * @param {string=} response.pluginName Optional. Name of the plugin to be checked.
+ * @param {string} response.errorCode Error code for the error that occurred.
+ * @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' ),
+ buttonText = _x( 'Activate', 'plugin' ),
+ ariaLabel = sprintf(
+ /* translators: 1: Plugin name, 2. The reason the plugin cannot be activated. */
+ _x( 'Cannot activate %1$s. %2$s', 'plugin' ),
+ response.pluginName,
+ response.errorMessage
+ ),
+ errorMessage;
+
+ if ( ! wp.updates.isValidResponse( response, 'check-dependencies' ) ) {
+ return;
+ }
+
+ errorMessage = sprintf(
+ /* translators: %s: Error string for a failed activation. */
+ __( 'Activation failed: %s' ),
+ response.errorMessage
+ );
wp.a11y.speak( errorMessage, 'assertive' );
-
- $document.trigger( 'wp-plugin-install-error', response );
+ $document.trigger( 'wp-check-plugin-dependencies-error', response );
+
+ $message
+ .removeClass( 'install-now installed updated-message' )
+ .addClass( 'activate-now button-primary' )
+ .attr( 'aria-label', ariaLabel )
+ .text( buttonText );
+
+ if ( 'plugin-information-footer' === $message.parent().attr('id' ) ) {
+ wp.updates.setCardButtonStatus(
+ {
+ status: 'dependencies-check-failed',
+ slug: response.slug,
+ removeClasses: 'install-now installed updated-message',
+ addClasses: 'activate-now button-primary',
+ text: buttonText,
+ ariaLabel: ariaLabel
+ }
+ );
+ }
+ };
+
+ /**
+ * Sends an Ajax request to the server to activate a plugin.
+ *
+ * @since 6.5.0
+ *
+ * @param {Object} args Arguments.
+ * @param {string} args.name The name of the plugin.
+ * @param {string} args.slug Plugin identifier in the WordPress.org Plugin repository.
+ * @param {string} args.plugin The plugin file, relative to the plugins directory.
+ * @param {activatePluginSuccess=} args.success Optional. Success callback. Default: wp.updates.activatePluginSuccess
+ * @param {activatePluginError=} args.error Optional. Error callback. Default: wp.updates.activatePluginError
+ * @return {$.promise} A jQuery promise that represents the request,
+ * decorated with an abort() method.
+ */
+ wp.updates.activatePlugin = function( args ) {
+ var $message = $( '.plugin-card-' + args.slug + ', #plugin-information-footer' ).find( '.activate-now, .activating-message' );
+
+ args = _.extend( {
+ success: wp.updates.activatePluginSuccess,
+ error: wp.updates.activatePluginError
+ }, args );
+
+ wp.a11y.speak( __( 'Activating... please wait.' ) );
+ $document.trigger( 'wp-activating-plugin', args );
+
+ if ( 'plugin-information-footer' === $message.parent().attr( 'id' ) ) {
+ wp.updates.setCardButtonStatus(
+ {
+ status: 'activating-plugin',
+ slug: args.slug,
+ removeClasses: 'installed updated-message button-primary',
+ addClasses: 'activating-message',
+ text: __( 'Activating...' ),
+ ariaLabel: sprintf(
+ /* translators: %s: Plugin name. */
+ _x( 'Activating %s', 'plugin' ),
+ args.name
+ )
+ }
+ );
+ }
+
+ return wp.updates.ajax( 'activate-plugin', args );
+ };
+
+ /**
+ * Updates the UI appropriately after a successful plugin activation.
+ *
+ * @since 6.5.0
+ *
+ * @param {Object} response Response from the server.
+ * @param {string} response.slug Slug of the activated plugin.
+ * @param {string} response.pluginName Name of the activated plugin.
+ * @param {string} response.plugin The plugin file, relative to the plugins directory.
+ */
+ wp.updates.activatePluginSuccess = function( response ) {
+ var $message = $( '.plugin-card-' + response.slug + ', #plugin-information-footer' ).find( '.activating-message' ),
+ buttonText = _x( 'Activated!', 'plugin' ),
+ ariaLabel = sprintf(
+ /* translators: %s: The plugin name. */
+ '%s activated successfully.',
+ response.pluginName
+ );
+
+ wp.a11y.speak( __( 'Activation completed successfully.' ) );
+ $document.trigger( 'wp-plugin-activate-success', response );
+
+ $message
+ .removeClass( 'activating-message' )
+ .addClass( 'activated-message button-disabled' )
+ .attr( 'aria-label', ariaLabel )
+ .text( buttonText );
+
+ if ( 'plugin-information-footer' === $message.parent().attr( 'id' ) ) {
+ wp.updates.setCardButtonStatus(
+ {
+ status: 'activated-plugin',
+ slug: response.slug,
+ removeClasses: 'activating-message',
+ addClasses: 'activated-message button-disabled',
+ text: buttonText,
+ ariaLabel: ariaLabel
+ }
+ );
+ }
+
+ setTimeout( function() {
+ $message.removeClass( 'activated-message' )
+ .text( _x( 'Active', 'plugin' ) );
+
+ if ( 'plugin-information-footer' === $message.parent().attr( 'id' ) ) {
+ wp.updates.setCardButtonStatus(
+ {
+ status: 'plugin-active',
+ slug: response.slug,
+ removeClasses: 'activated-message',
+ text: _x( 'Active', 'plugin' ),
+ ariaLabel: sprintf(
+ /* translators: %s: The plugin name. */
+ '%s is active.',
+ response.pluginName
+ )
+ }
+ );
+ }
+ }, 1000 );
+ };
+
+ /**
+ * Updates the UI appropriately after a failed plugin activation.
+ *
+ * @since 6.5.0
+ *
+ * @param {Object} response Response from the server.
+ * @param {string} response.slug Slug of the plugin to be activated.
+ * @param {string=} response.pluginName Optional. Name of the plugin to be activated.
+ * @param {string} response.errorCode Error code for the error that occurred.
+ * @param {string} response.errorMessage The error that occurred.
+ */
+ wp.updates.activatePluginError = function( response ) {
+ var $message = $( '.plugin-card-' + response.slug + ', #plugin-information-footer' ).find( '.activating-message' ),
+ buttonText = __( 'Activation failed.' ),
+ ariaLabel = sprintf(
+ /* translators: %s: Plugin name. */
+ _x( '%s activation failed', 'plugin' ),
+ response.pluginName
+ ),
+ errorMessage;
+
+ if ( ! wp.updates.isValidResponse( response, 'activate' ) ) {
+ return;
+ }
+
+ errorMessage = sprintf(
+ /* translators: %s: Error string for a failed activation. */
+ __( 'Activation failed: %s' ),
+ response.errorMessage
+ );
+
+ wp.a11y.speak( errorMessage, 'assertive' );
+ $document.trigger( 'wp-plugin-activate-error', response );
+
+ $message
+ .removeClass( 'install-now installed activating-message' )
+ .addClass( 'button-disabled' )
+ .attr( 'aria-label', ariaLabel )
+ .text( buttonText );
+
+ if ( 'plugin-information-footer' === $message.parent().attr( 'id' ) ) {
+ wp.updates.setCardButtonStatus(
+ {
+ status: 'plugin-activation-failed',
+ slug: response.slug,
+ removeClasses: 'install-now installed activating-message',
+ addClasses: 'button-disabled',
+ text: buttonText,
+ ariaLabel: ariaLabel
+ }
+ );
+ }
};
/**
@@ -913,7 +1300,7 @@
pluginName
)
)
- .text( __( 'Install Now' ) );
+ .text( _x( 'Install Now', 'plugin' ) );
wp.a11y.speak( errorMessage, 'assertive' );
@@ -1067,7 +1454,7 @@
$itemsCount.text(
sprintf(
/* translators: %s: The remaining number of plugins. */
- _nx( '%s item', '%s items', 'plugin/plugins', remainingCount ),
+ _nx( '%s item', '%s items', remainingCount, 'plugin/plugins' ),
remainingCount
)
);
@@ -1416,7 +1803,7 @@
response.themeName
)
)
- .text( __( 'Activate' ) );
+ .text( _x( 'Activate', 'theme' ) );
}
}
@@ -1614,6 +2001,14 @@
} );
}
+ // DecrementCount from update count.
+ if ( 'themes' === pagenow ) {
+ var theme = _.find( _wpThemeSettings.themes, { id: response.slug } );
+ if ( theme.hasUpdate ) {
+ wp.updates.decrementCount( 'theme' );
+ }
+ }
+
wp.a11y.speak( _x( 'Deleted!', 'theme' ) );
$document.trigger( 'wp-theme-delete-success', response );
@@ -1865,7 +2260,7 @@
// Remove any existing error.
$filesystemForm.find( '.notice' ).remove();
- $filesystemForm.find( '#request-filesystem-credentials-title' ).after( '<div class="notice notice-alt notice-error"><p>' + message + '</p></div>' );
+ $filesystemForm.find( '#request-filesystem-credentials-title' ).after( '<div class="notice notice-alt notice-error" role="alert"><p>' + message + '</p></div>' );
};
/**
@@ -1960,6 +2355,16 @@
errorMessage = __( 'Installation failed: %s' );
break;
+ case 'check-dependencies':
+ /* translators: %s: Error string for a failed dependencies check. */
+ errorMessage = __( 'Dependencies check failed: %s' );
+ break;
+
+ case 'activate':
+ /* translators: %s: Error string for a failed activation. */
+ errorMessage = __( 'Activation failed: %s' );
+ break;
+
case 'delete':
/* translators: %s: Error string for a failed deletion. */
errorMessage = __( 'Deletion failed: %s' );
@@ -2015,7 +2420,7 @@
};
$( function() {
- var $pluginFilter = $( '#plugin-filter' ),
+ var $pluginFilter = $( '#plugin-filter, #plugin-information-footer' ),
$bulkActionForm = $( '#bulk-action-form' ),
$filesystemForm = $( '#request-filesystem-credentials-form' ),
$filesystemModal = $( '#request-filesystem-credentials-dialog' ),
@@ -2220,7 +2625,7 @@
$message
.removeClass( 'updating-message' )
- .text( __( 'Install Now' ) );
+ .text( _x( 'Install Now', 'plugin' ) );
wp.a11y.speak( __( 'Update canceled.' ) );
} );
@@ -2232,6 +2637,19 @@
} );
/**
+ * Click handler for plugin activations in plugin activation modal view.
+ *
+ * @since 6.5.0
+ * @since 6.5.4 Redirect the parent window to the activation URL.
+ *
+ * @param {Event} event Event interface.
+ */
+ $document.on( 'click', '#plugin-information-footer .activate-now', function( event ) {
+ event.preventDefault();
+ window.parent.location.href = $( event.target ).attr( 'href' );
+ });
+
+ /**
* Click handler for importer plugins installs in the Import screen.
*
* @since 4.6.0
@@ -2263,7 +2681,7 @@
pluginName
)
)
- .text( __( 'Install Now' ) );
+ .text( _x( 'Install Now', 'plugin' ) );
wp.a11y.speak( __( 'Update canceled.' ) );
} );
@@ -2460,6 +2878,13 @@
return;
}
+ // Don't add items to the update queue again, even if the user clicks the update button several times.
+ if ( 'update-selected' === bulkAction && $itemRow.hasClass( 'is-enqueued' ) ) {
+ return;
+ }
+
+ $itemRow.addClass( 'is-enqueued' );
+
// Add it to the queue.
wp.updates.queue.push( {
action: action,
@@ -2488,13 +2913,41 @@
wp.updates.adminNotice = wp.template( 'wp-bulk-updates-admin-notice' );
+ var successMessage = null;
+
+ if ( success ) {
+ if ( 'plugin' === response.update ) {
+ successMessage = sprintf(
+ /* translators: %s: Number of plugins. */
+ _n( '%s plugin successfully updated.', '%s plugins successfully updated.', success ),
+ success
+ );
+ } else {
+ successMessage = sprintf(
+ /* translators: %s: Number of themes. */
+ _n( '%s theme successfully updated.', '%s themes successfully updated.', success ),
+ success
+ );
+ }
+ }
+
+ var errorMessage = null;
+
+ if ( error ) {
+ errorMessage = sprintf(
+ /* translators: %s: Number of failed updates. */
+ _n( '%s update failed.', '%s updates failed.', error ),
+ error
+ );
+ }
+
wp.updates.addAdminNotice( {
id: 'bulk-action-notice',
className: 'bulk-action-notice',
- successes: success,
- errors: error,
- errorMessages: errorMessages,
- type: response.update
+ successMessage: successMessage,
+ errorMessage: errorMessage,
+ errorMessages: errorMessages,
+ type: response.update
} );
$bulkActionNotice = $( '#bulk-action-notice' ).on( 'click', 'button', function() {
@@ -2535,7 +2988,7 @@
data = {
_ajax_nonce: wp.updates.ajaxNonce,
- s: event.target.value,
+ s: encodeURIComponent( event.target.value ),
tab: 'search',
type: $( '#typeselector' ).val(),
pagenow: pagenow
@@ -2612,7 +3065,7 @@
$pluginSearch.on( 'keyup input', _.debounce( function( event ) {
var data = {
_ajax_nonce: wp.updates.ajaxNonce,
- s: event.target.value,
+ s: encodeURIComponent( event.target.value ),
pagenow: pagenow,
plugin_status: 'all'
},
@@ -2654,7 +3107,7 @@
sprintf(
/* translators: %s: Search query. */
__( 'Search results for: %s' ),
- '<strong>' + _.escape( data.s ) + '</strong>'
+ '<strong>' + _.escape( decodeURIComponent( data.s ) ) + '</strong>'
) ),
$oldSubTitle = $( '.wrap .subtitle' );
@@ -2750,35 +3203,6 @@
} );
/**
- * Click handler for installing a plugin from the details modal on `plugin-install.php`.
- *
- * @since 4.6.0
- *
- * @param {Event} event Event interface.
- */
- $( '#plugin_install_from_iframe' ).on( 'click', function( event ) {
- var target = window.parent === window ? null : window.parent,
- install;
-
- $.support.postMessage = !! window.postMessage;
-
- if ( false === $.support.postMessage || null === target || -1 !== window.parent.location.pathname.indexOf( 'index.php' ) ) {
- return;
- }
-
- event.preventDefault();
-
- install = {
- action: 'install-plugin',
- data: {
- slug: $( this ).data( 'slug' )
- }
- };
-
- target.postMessage( JSON.stringify( install ), window.location.origin );
- } );
-
- /**
* Handles postMessage events.
*
* @since 4.2.0
@@ -2801,7 +3225,45 @@
return;
}
- if ( ! message || 'undefined' === typeof message.action ) {
+ if ( ! message ) {
+ return;
+ }
+
+ if (
+ 'undefined' !== typeof message.status &&
+ 'undefined' !== typeof message.slug &&
+ 'undefined' !== typeof message.text &&
+ 'undefined' !== typeof message.ariaLabel
+ ) {
+ var $card = $( '.plugin-card-' + message.slug ),
+ $message = $card.find( '[data-slug="' + message.slug + '"]' );
+
+ if ( 'undefined' !== typeof message.removeClasses ) {
+ $message.removeClass( message.removeClasses );
+ }
+
+ if ( 'undefined' !== typeof message.addClasses ) {
+ $message.addClass( message.addClasses );
+ }
+
+ if ( '' === message.ariaLabel ) {
+ $message.removeAttr( 'aria-label' );
+ } else {
+ $message.attr( 'aria-label', message.ariaLabel );
+ }
+
+ if ( 'dependencies-check-success' === message.status ) {
+ $message
+ .attr( 'data-name', message.pluginName )
+ .attr( 'data-slug', message.slug )
+ .attr( 'data-plugin', message.plugin )
+ .attr( 'href', message.href );
+ }
+
+ $message.text( message.text );
+ }
+
+ if ( 'undefined' === typeof message.action ) {
return;
}
@@ -2815,9 +3277,9 @@
case 'install-plugin':
case 'update-plugin':
- /* jscs:disable requireCamelCaseOrUpperCaseIdentifiers */
- window.tb_remove();
- /* jscs:enable */
+ if ( 'undefined' === typeof message.data || 'undefined' === typeof message.data.slug ) {
+ return;
+ }
message.data = wp.updates._addCallbacks( message.data, message.action );