';
if ( ! current_user_can( 'update_plugins' ) ) {
printf( __('There is a new version of %1$s available.
View version %4$s details.'), $plugin_name, esc_url($details_url), esc_attr($plugin_name), $r->new_version );
} elseif ( empty($r->package) ) {
printf( __('There is a new version of %1$s available.
View version %4$s details.
Automatic update is unavailable for this plugin.'), $plugin_name, esc_url($details_url), esc_attr($plugin_name), $r->new_version );
} else {
- printf( __('There is a new version of %1$s available.
View version %4$s details or
update now.'), $plugin_name, esc_url($details_url), esc_attr($plugin_name), $r->new_version, wp_nonce_url( self_admin_url('update.php?action=upgrade-plugin&plugin=') . $file, 'upgrade-plugin_' . $file) );
+ printf( __( 'There is a new version of %1$s available.
View version %4$s details or
update now.' ), $plugin_name, esc_url( $details_url ), esc_attr( $plugin_name ), $r->new_version, wp_nonce_url( self_admin_url( 'update.php?action=upgrade-plugin&plugin=' ) . $file, 'upgrade-plugin_' . $file ) );
}
/**
* Fires at the end of the update message container in each
diff --git a/src/wp-admin/js/plugin-install.js b/src/wp-admin/js/plugin-install.js
index 7403769e8b..36a6bdc57d 100644
--- a/src/wp-admin/js/plugin-install.js
+++ b/src/wp-admin/js/plugin-install.js
@@ -69,8 +69,4 @@ jQuery( document ).ready( function( $ ) {
$( '#section-holder div.section' ).hide(); // Hide 'em all.
$( '#section-' + tab ).show();
});
-
- $( 'a.install-now' ).click( function() {
- return confirm( plugininstallL10n.ays );
- });
});
diff --git a/src/wp-admin/js/updates.js b/src/wp-admin/js/updates.js
index b03e4ba8f0..025d977ece 100644
--- a/src/wp-admin/js/updates.js
+++ b/src/wp-admin/js/updates.js
@@ -5,43 +5,370 @@ window.wp = window.wp || {};
wp.updates = {};
/**
- * Decrement update counts throughout the various menus
+ * User nonce for ajax calls.
+ *
+ * @since 4.2.0
+ *
+ * @var string
+ */
+ wp.updates.ajaxNonce = window._wpUpdatesSettings.ajax_nonce;
+
+ /**
+ * Localized strings.
+ *
+ * @since 4.2.0
+ *
+ * @var object
+ */
+ wp.updates.l10n = window._wpUpdatesSettings.l10n;
+
+ /**
+ * Flag if we're waiting for an install/update to complete.
+ *
+ * @since 4.2.0
+ *
+ * @var bool
+ */
+ wp.updates.updateLock = false;
+
+ /**
+ * If the user tries to install/update a plugin while an install/update is
+ * already happening, it can be placed in this queue to perform later.
+ *
+ * @since 4.2.0
+ *
+ * @var array
+ */
+ wp.updates.updateQueue = [];
+
+ /**
+ * Decrement update counts throughout the various menus.
+ *
+ * @since 3.9.0
*
* @param {string} updateType
*/
wp.updates.decrementCount = function( upgradeType ) {
- var count, pluginCount, $elem;
+ var count,
+ pluginCount,
+ $adminBarUpdateCount = $( '#wp-admin-bar-updates .ab-label' ),
+ $dashboardNavMenuUpdateCount = $( 'a[href="update-core.php"] .update-plugins' )
+ $pluginsMenuItem = $( '#menu-plugins' );
- $elem = $( '#wp-admin-bar-updates .ab-label' );
- count = $elem.text();
+
+ count = $adminBarUpdateCount.text();
count = parseInt( count, 10 ) - 1;
if ( count < 0 || isNaN( count ) ) {
return;
}
$( '#wp-admin-bar-updates .ab-item' ).removeAttr( 'title' );
- $elem.text( count );
+ $adminBarUpdateCount.text( count );
- $elem = $( 'a[href="update-core.php"] .update-plugins' );
- $elem.each( function( index, elem ) {
+
+ $dashboardNavMenuUpdateCount.each( function( index, elem ) {
elem.className = elem.className.replace( /count-\d+/, 'count-' + count );
} );
- $elem.removeAttr( 'title' );
- $elem.find( '.update-count' ).text( count );
+ $dashboardNavMenuUpdateCount.removeAttr( 'title' );
+ $dashboardNavMenuUpdateCount.find( '.update-count' ).text( count );
if ( 'plugin' === upgradeType ) {
- $elem = $( '#menu-plugins' );
- pluginCount = $elem.find( '.plugin-count' ).eq(0).text();
+ pluginCount = $pluginsMenuItem.find( '.plugin-count' ).eq(0).text();
pluginCount = parseInt( pluginCount, 10 ) - 1;
if ( pluginCount < 0 || isNaN( pluginCount ) ) {
return;
}
- $elem.find( '.plugin-count' ).text( pluginCount );
- $elem.find( '.update-plugins' ).each( function( index, elem ) {
+ $pluginsMenuItem.find( '.plugin-count' ).text( pluginCount );
+ $pluginsMenuItem.find( '.update-plugins' ).each( function( index, elem ) {
elem.className = elem.className.replace( /count-\d+/, 'count-' + pluginCount );
} );
+
+ if (pluginCount > 0 ) {
+ $( '.subsubsub .upgrade .count' ).text( '(' + pluginCount + ')' );
+ } else {
+ $( '.subsubsub .upgrade' ).remove();
+ }
}
};
+ /**
+ * Send an Ajax request to the server to update a plugin.
+ *
+ * @since 4.2.0
+ *
+ * @param {string} plugin
+ * @param {string} slug
+ */
+ wp.updates.updatePlugin = function( plugin, slug ) {
+ var $message;
+ if ( 'plugins' === pagenow || 'plugins-network' === pagenow ) {
+ $message = $( '#' + slug ).next().find( '.update-message' );
+ } else if ( 'plugin-install' === pagenow ) {
+ $message = $( '.plugin-card-' + slug ).find( '.update-now' );
+ }
+
+ $message.addClass( 'updating-message' );
+ $message.text( wp.updates.l10n.updating );
+
+ if ( wp.updates.updateLock ) {
+ wp.updates.updateQueue.push( {
+ type: 'update-plugin',
+ data: {
+ plugin: plugin,
+ slug: slug
+ }
+ } );
+ return;
+ }
+
+ wp.updates.updateLock = true;
+
+ var data = {
+ 'action': 'update-plugin',
+ '_ajax_nonce': wp.updates.ajaxNonce,
+ 'plugin': plugin,
+ 'slug': slug
+ };
+
+ $.ajax( {
+ type: 'post',
+ url: ajaxurl,
+ data: data,
+ complete: wp.updates.updateRequestComplete
+ } );
+ };
+
+ /**
+ * After an update attempt has completed, deal with the response.
+ *
+ * @since 4.2.0
+ *
+ * @param {jqXHR} jqxhr The jQuery XMLHttpRequest for the request.
+ */
+ wp.updates.updateRequestComplete = function( jqxhr ) {
+ wp.updates.updateLock = false;
+ if ( jqxhr.responseJSON && jqxhr.responseJSON.success ) {
+ wp.updates.updateSuccess( jqxhr.responseJSON );
+ } else {
+ var alertText = wp.updates.l10n.updateFailed;
+ if ( jqxhr.responseJSON && jqxhr.responseJSON.data && jqxhr.responseJSON.data.error ) {
+ alertText += ': ' + jqxhr.responseJSON.data.error;
+ }
+ alert( alertText );
+ if ( jqxhr.responseJSON && jqxhr.responseJSON.data && jqxhr.responseJSON.data.slug ) {
+ wp.updates.updateError( jqxhr.responseJSON );
+ }
+ }
+ /**
+ * Check the queue.
+ */
+ wp.updates.queueChecker();
+ }
+
+ /**
+ * On a successful plugin update, update the UI with the result.
+ *
+ * @since 4.2.0
+ *
+ * @param {object} response
+ */
+ wp.updates.updateSuccess = function( response ) {
+ var $message;
+ if ( 'plugins' === pagenow || 'plugins-network' === pagenow ) {
+ $message = $( '#' + response.data.slug ).next().find( '.update-message' );
+ $( '#' + response.data.slug ).addClass( 'updated' ).removeClass( 'update' );
+ $( '#' + response.data.slug + '-update' ).addClass( 'updated' ).removeClass( 'update' );
+ } else if ( 'plugin-install' === pagenow ) {
+ $message = $( '.plugin-card-' + response.data.slug ).find( '.update-now' );
+ $message.addClass( 'button-disabled' );
+ }
+
+ $message.removeClass( 'updating-message' ).addClass( 'updated-message' );
+ $message.text( wp.updates.l10n.updated );
+
+ wp.updates.decrementCount( 'plugin' );
+ };
+
+ /**
+ * On a plugin update error, update the UI appropriately.
+ *
+ * @since 4.2.0
+ *
+ * @param {object} response
+ */
+ wp.updates.updateError = function( response ) {
+ var $message;
+ if ( 'plugins' === pagenow || 'plugins-network' === pagenow ) {
+ $message = $( '#' + response.data.slug ).next().find( '.update-message' );
+ } else if ( 'plugin-install' === pagenow ) {
+ $message = $( '.plugin-card-' + response.data.slug ).find( '.update-now' );
+ }
+ $message.removeClass( 'updating-message' );
+ $message.text( wp.updates.l10n.updateFailed );
+ };
+
+ /**
+ * Send an Ajax request to the server to install a plugin.
+ *
+ * @since 4.2.0
+ *
+ * @param {string} slug
+ */
+ wp.updates.installPlugin = function( slug ) {
+ var $message = $( '.plugin-card-' + slug ).find( '.install-now' );
+
+ $message.addClass( 'updating-message' );
+ $message.text( wp.updates.l10n.installing );
+
+ if ( wp.updates.updateLock ) {
+ wp.updates.updateQueue.push( {
+ type: 'install-plugin',
+ data: {
+ slug: slug
+ }
+ } );
+ return;
+ }
+
+ wp.updates.updateLock = true;
+
+ var data = {
+ 'action': 'install-plugin',
+ '_ajax_nonce': wp.updates.ajaxNonce,
+ 'slug': slug
+ };
+
+ $.ajax( {
+ type: 'post',
+ url: ajaxurl,
+ data: data,
+ complete: wp.updates.installRequestComplete
+ } );
+ };
+
+
+ /**
+ * After an installation attempt has completed, deal with the response.
+ *
+ * @since 4.2.0
+ *
+ * @param {jqXHR} jqxhr The jQuery XMLHttpRequest for the request.
+ */
+ wp.updates.installRequestComplete = function( jqxhr ) {
+ wp.updates.updateLock = false;
+ if ( jqxhr.responseJSON && jqxhr.responseJSON.success ) {
+ wp.updates.installSuccess( jqxhr.responseJSON );
+ } else {
+ var alertText = wp.updates.l10n.installFailed;
+ if ( jqxhr.responseJSON && jqxhr.responseJSON.data && jqxhr.responseJSON.data.error ) {
+ alertText += ': ' + jqxhr.responseJSON.data.error;
+ }
+ alert( alertText );
+ if ( jqxhr.responseJSON && jqxhr.responseJSON.data && jqxhr.responseJSON.data.slug ) {
+ wp.updates.installError( jqxhr.responseJSON );
+ }
+ }
+ /**
+ * Check the queue.
+ */
+ wp.updates.queueChecker();
+ };
+
+ /**
+ * On plugin install success, update the UI with the result.
+ *
+ * @since 4.2.0
+ *
+ * @param {object} response
+ */
+ wp.updates.installSuccess = function( response ) {
+ var $message = $( '.plugin-card-' + response.data.slug ).find( '.install-now' );
+
+ $message.removeClass( 'updating-message' ).addClass( 'updated-message button-disabled' );
+ $message.text( wp.updates.l10n.installed );
+ };
+
+ /**
+ * On plugin install failure, update the UI appropriately.
+ *
+ * @since 4.2.0
+ *
+ * @param {object} response
+ */
+ wp.updates.installError = function( response ) {
+ var $message = $( '.plugin-card-' + response.data.slug ).find( '.install-now' );
+
+ $message.removeClass( 'updating-message' );
+ $message.text( wp.updates.l10n.installNow );
+ };
+
+
+ /**
+ * If an install/update job has been placed in the queue, queueChecker pulls it out and runs it.
+ *
+ * @since 4.2.0
+ */
+ wp.updates.queueChecker = function() {
+ if ( wp.updates.updateLock || wp.updates.updateQueue.length <= 0 ) {
+ return;
+ }
+
+ var job = wp.updates.updateQueue.shift();
+
+ switch ( job.type ) {
+ case 'update-plugin':
+ wp.updates.updatePlugin( job.data.plugin, job.data.slug );
+ break;
+ case 'install-plugin':
+ wp.updates.installPlugin( job.data.slug );
+ break;
+ default:
+ console.log( 'Failed to exect queued update job.' );
+ console.log( job );
+ break;
+ }
+ };
+
+ $( document ).ready( function() {
+ $( '.plugin-update-tr .update-link' ).on( 'click', function( e ) {
+ e.preventDefault();
+ var $row = $( e.target ).parents( '.plugin-update-tr' );
+ wp.updates.updatePlugin( $row.data( 'plugin' ), $row.data( 'slug' ) );
+ } );
+
+ $( '#bulk-action-form' ).on( 'submit', function( e ) {
+ var checkbox, plugin, slug;
+
+ if ( $( '#bulk-action-selector-top' ).val() == 'update-selected' ) {
+ e.preventDefault();
+
+ $( 'input[name="checked[]"]:checked' ).each( function( index, elem ) {
+ $checkbox = $( elem );
+ plugin = $checkbox.val();
+ slug = $checkbox.parents( 'tr' ).prop( 'id' );
+
+ wp.updates.updatePlugin( plugin, slug );
+
+ $checkbox.attr( 'checked', false );
+ } );
+ }
+ } );
+
+ $( '.plugin-card .update-now' ).on( 'click', function( e ) {
+ e.preventDefault();
+ $button = $( e.target );
+ wp.updates.updatePlugin( $button.data( 'plugin' ), $button.data( 'slug' ) );
+ } );
+
+ $( '.plugin-card .install-now' ).on( 'click', function( e ) {
+ e.preventDefault();
+ $button = $( e.target );
+ if ( $button.hasClass( 'button-disabled' ) ) {
+ return;
+ }
+ wp.updates.installPlugin( $button.data( 'slug' ) );
+ } );
+ } );
+
$( window ).on( 'message', function( e ) {
var event = e.originalEvent,
message,
diff --git a/src/wp-admin/plugin-install.php b/src/wp-admin/plugin-install.php
index e2431eb9b5..03085c7813 100644
--- a/src/wp-admin/plugin-install.php
+++ b/src/wp-admin/plugin-install.php
@@ -54,6 +54,8 @@ if ( 'plugin-information' != $tab )
$body_id = $tab;
+wp_enqueue_script( 'updates' );
+
/**
* Fires before each tab on the Install Plugins screen is loaded.
*
diff --git a/src/wp-admin/plugins.php b/src/wp-admin/plugins.php
index 29bca4ab7e..629fdbff53 100644
--- a/src/wp-admin/plugins.php
+++ b/src/wp-admin/plugins.php
@@ -23,6 +23,8 @@ $s = isset($_REQUEST['s']) ? urlencode($_REQUEST['s']) : '';
// Clean up request URI from temporary args for screen options/paging uri's to work as expected.
$_SERVER['REQUEST_URI'] = remove_query_arg(array('error', 'deleted', 'activate', 'activate-multi', 'deactivate', 'deactivate-multi', '_error_nonce'), $_SERVER['REQUEST_URI']);
+wp_enqueue_script( 'updates' );
+
if ( $action ) {
switch ( $action ) {
@@ -460,7 +462,7 @@ do_action( 'pre_current_active_plugins', $plugins['all'] );
search_box( __( 'Search Installed Plugins' ), 'plugin' ); ?>
-