Request FTP and SSH credentials when needed during shiny updates
This is a restoration of [31749] which was reverted in [31755]. It includes a number of enhancements from the original version. Namely: * Not doing a credential check in src/wp-includes/script-loader.php * Add new function `wp_print_request_filesystem_credentials_modal` * update the version number in the list table when a plugin is updated UI still needs further work, but this basic version should enable more testing Props ericlewis, jorbin See #31528 Built from https://develop.svn.wordpress.org/trunk@31811 git-svn-id: http://core.svn.wordpress.org/trunk@31793 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
parent
f26a2e8113
commit
2d64637ff8
|
@ -848,6 +848,27 @@ table.form-table td .updated p {
|
|||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
Credentials check dialog for Install and Updates
|
||||
------------------------------------------------------------------------------*/
|
||||
|
||||
.request-filesystem-credentials-dialog {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.request-filesystem-credentials-dialog .notification-dialog {
|
||||
top: 15%;
|
||||
}
|
||||
|
||||
.request-filesystem-credentials-dialog-content {
|
||||
margin: 25px;
|
||||
}
|
||||
|
||||
.request-filesystem-credentials-dialog-content input[type="text"],
|
||||
.request-filesystem-credentials-dialog-content input[type="password"] {
|
||||
width: 85%;
|
||||
}
|
||||
|
||||
/* =Media Queries
|
||||
-------------------------------------------------------------- */
|
||||
|
||||
|
|
|
@ -848,6 +848,27 @@ table.form-table td .updated p {
|
|||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
Credentials check dialog for Install and Updates
|
||||
------------------------------------------------------------------------------*/
|
||||
|
||||
.request-filesystem-credentials-dialog {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.request-filesystem-credentials-dialog .notification-dialog {
|
||||
top: 15%;
|
||||
}
|
||||
|
||||
.request-filesystem-credentials-dialog-content {
|
||||
margin: 25px;
|
||||
}
|
||||
|
||||
.request-filesystem-credentials-dialog-content input[type="text"],
|
||||
.request-filesystem-credentials-dialog-content input[type="password"] {
|
||||
width: 85%;
|
||||
}
|
||||
|
||||
/* =Media Queries
|
||||
-------------------------------------------------------------- */
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -2913,6 +2913,10 @@ function wp_ajax_install_plugin() {
|
|||
if ( is_wp_error( $result ) ) {
|
||||
$status['error'] = $result->get_error_message();
|
||||
wp_send_json_error( $status );
|
||||
} else if ( is_null( $result ) ) {
|
||||
$status['errorCode'] = 'unable_to_connect_to_filesystem';
|
||||
$status['error'] = __( 'Unable to connect to the filesystem. Please confirm your credentials.' );
|
||||
wp_send_json_error( $status );
|
||||
}
|
||||
|
||||
$plugin_status = install_plugin_install_status( $api );
|
||||
|
@ -2936,7 +2940,13 @@ function wp_ajax_update_plugin() {
|
|||
'update' => 'plugin',
|
||||
'plugin' => $plugin,
|
||||
'slug' => sanitize_key( $_POST['slug'] ),
|
||||
'oldVersion' => '',
|
||||
'newVersion' => '',
|
||||
);
|
||||
$plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin );
|
||||
if ( $plugin_data['Version'] ) {
|
||||
$status['oldVersion'] = sprintf( __( 'Version %s' ), $plugin_data['Version'] );
|
||||
}
|
||||
|
||||
if ( ! current_user_can( 'update_plugins' ) ) {
|
||||
$status['error'] = __( 'You do not have sufficient permissions to update plugins on this site.' );
|
||||
|
@ -2956,15 +2966,31 @@ function wp_ajax_update_plugin() {
|
|||
$result = $upgrader->bulk_upgrade( array( $plugin ) );
|
||||
|
||||
if ( is_array( $result ) ) {
|
||||
$result = $result[ $plugin ];
|
||||
}
|
||||
|
||||
if ( is_wp_error( $result ) ) {
|
||||
$status['error'] = $result->get_error_message();
|
||||
$plugin_update_data = current( $result );
|
||||
/*
|
||||
* If the `update_plugins` site transient is empty (e.g. when you update
|
||||
* two plugins in quick succession before the transient repopulates),
|
||||
* this may be the return.
|
||||
*
|
||||
* Preferably something can be done to ensure `update_plugins` isn't empty.
|
||||
* For now, surface some sort of error here.
|
||||
*/
|
||||
if ( $plugin_update_data === true ) {
|
||||
wp_send_json_error( $status );
|
||||
}
|
||||
|
||||
$plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin );
|
||||
if ( $plugin_data['Version'] ) {
|
||||
$status['newVersion'] = sprintf( __( 'Version %s' ), $plugin_data['Version'] );
|
||||
}
|
||||
wp_send_json_success( $status );
|
||||
} else if ( is_wp_error( $result ) ) {
|
||||
$status['error'] = $result->get_error_message();
|
||||
wp_send_json_error( $status );
|
||||
} else if ( is_bool( $result ) && ! $result ) {
|
||||
$status['errorCode'] = 'unable_to_connect_to_filesystem';
|
||||
$status['error'] = __( 'Unable to connect to the filesystem. Please confirm your credentials.' );
|
||||
wp_send_json_error( $status );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1192,3 +1192,29 @@ submit_button( __( 'Proceed' ), 'button', 'upgrade' );
|
|||
<?php
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the credentials modal when needed
|
||||
*
|
||||
* @since 4.2.0
|
||||
*/
|
||||
function wp_print_request_filesystem_credentials_modal() {
|
||||
$filesystem_method = get_filesystem_method();
|
||||
ob_start();
|
||||
$filesystem_credentials_are_stored = request_filesystem_credentials( self_admin_url() );
|
||||
ob_end_clean();
|
||||
$request_filesystem_credentials = ( $filesystem_method != 'direct' && ! $filesystem_credentials_are_stored );
|
||||
if ( ! $request_filesystem_credentials ) {
|
||||
return;
|
||||
}
|
||||
?>
|
||||
<div id="request-filesystem-credentials-dialog" class="notification-dialog-wrap request-filesystem-credentials-dialog">
|
||||
<div class="notification-dialog-background"></div>
|
||||
<div class="notification-dialog">
|
||||
<div class="request-filesystem-credentials-dialog-content">
|
||||
<?php request_filesystem_credentials( site_url() ); ?>
|
||||
<div>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
|
|
@ -21,6 +21,35 @@ window.wp = window.wp || {};
|
|||
*/
|
||||
wp.updates.l10n = window._wpUpdatesSettings.l10n;
|
||||
|
||||
/**
|
||||
* Whether filesystem credentials need to be requested from the user.
|
||||
*
|
||||
* @since 4.2.0
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
wp.updates.shouldRequestFilesystemCredentials = null;
|
||||
|
||||
/**
|
||||
* Filesystem credentials to be packaged along with the request.
|
||||
*
|
||||
* @since 4.2.0
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
wp.updates.filesystemCredentials = {
|
||||
ftp: {
|
||||
host: null,
|
||||
username: null,
|
||||
password: null,
|
||||
connectionType: null
|
||||
},
|
||||
ssh: {
|
||||
publicKey: null,
|
||||
privateKey: null
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Flag if we're waiting for an install/update to complete.
|
||||
*
|
||||
|
@ -30,6 +59,15 @@ window.wp = window.wp || {};
|
|||
*/
|
||||
wp.updates.updateLock = false;
|
||||
|
||||
/**
|
||||
* * Flag if we've done an install or update successfully.
|
||||
*
|
||||
* @since 4.2.0
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
wp.updates.updateDoneSuccessfully = 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.
|
||||
|
@ -123,15 +161,20 @@ window.wp = window.wp || {};
|
|||
wp.updates.updateLock = true;
|
||||
|
||||
var data = {
|
||||
'_ajax_nonce': wp.updates.ajaxNonce,
|
||||
'plugin': plugin,
|
||||
'slug': slug
|
||||
_ajax_nonce: wp.updates.ajaxNonce,
|
||||
plugin: plugin,
|
||||
slug: slug,
|
||||
username: wp.updates.filesystemCredentials.ftp.username,
|
||||
password: wp.updates.filesystemCredentials.ftp.password,
|
||||
hostname: wp.updates.filesystemCredentials.ftp.hostname,
|
||||
connection_type: wp.updates.filesystemCredentials.ftp.connectionType,
|
||||
public_key: wp.updates.filesystemCredentials.ssh.publicKey,
|
||||
private_key: wp.updates.filesystemCredentials.ssh.privateKey
|
||||
};
|
||||
|
||||
wp.ajax.post( 'update-plugin', data )
|
||||
.done( wp.updates.updateSuccess )
|
||||
.fail( wp.updates.updateError )
|
||||
.always( wp.updates.updateAlways );
|
||||
.fail( wp.updates.updateError );
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -147,6 +190,9 @@ window.wp = window.wp || {};
|
|||
$message = $( '#' + response.slug ).next().find( '.update-message' );
|
||||
$( '#' + response.slug ).addClass( 'updated' ).removeClass( 'update' );
|
||||
$( '#' + response.slug + '-update' ).addClass( 'updated' ).removeClass( 'update' );
|
||||
// Update the version number in the row.
|
||||
var newText = $( '#' + response.slug ).find('.plugin-version-author-uri').html().replace( response.oldVersion, response.newVersion );
|
||||
$( '#' + response.slug ).find('.plugin-version-author-uri').html( newText );
|
||||
} else if ( 'plugin-install' === pagenow ) {
|
||||
$message = $( '.plugin-card-' + response.slug ).find( '.update-now' );
|
||||
$message.addClass( 'button-disabled' );
|
||||
|
@ -157,6 +203,15 @@ window.wp = window.wp || {};
|
|||
wp.a11y.speak( wp.updates.l10n.updatedMsg );
|
||||
|
||||
wp.updates.decrementCount( 'plugin' );
|
||||
|
||||
wp.updates.updateDoneSuccessfully = true;
|
||||
|
||||
/*
|
||||
* The lock can be released since the update was successful,
|
||||
* and any other updates can commence.
|
||||
*/
|
||||
wp.updates.updateLock = false;
|
||||
wp.updates.queueChecker();
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -168,6 +223,11 @@ window.wp = window.wp || {};
|
|||
*/
|
||||
wp.updates.updateError = function( response ) {
|
||||
var $message;
|
||||
wp.updates.updateDoneSuccessfully = false;
|
||||
if ( response.errorCode && response.errorCode == 'unable_to_connect_to_filesystem' ) {
|
||||
wp.updates.credentialError( response, 'update-plugin' );
|
||||
return;
|
||||
}
|
||||
if ( 'plugins' === pagenow || 'plugins-network' === pagenow ) {
|
||||
$message = $( '#' + response.slug ).next().find( '.update-message' );
|
||||
} else if ( 'plugin-install' === pagenow ) {
|
||||
|
@ -176,18 +236,23 @@ window.wp = window.wp || {};
|
|||
$message.removeClass( 'updating-message' );
|
||||
$message.text( wp.updates.l10n.updateFailed );
|
||||
wp.a11y.speak( wp.updates.l10n.updateFailed );
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* After an update attempt has completed, check the queue.
|
||||
* Show an error message in the request for credentials form.
|
||||
*
|
||||
* @param {string} message
|
||||
* @since 4.2.0
|
||||
*/
|
||||
wp.updates.updateAlways = function() {
|
||||
wp.updates.updateLock = false;
|
||||
wp.updates.queueChecker();
|
||||
};
|
||||
wp.updates.showErrorInCredentialsForm = function( message ) {
|
||||
var $notificationDialog = $( '.notification-dialog' );
|
||||
|
||||
// Remove any existing error
|
||||
$notificationDialog.find( '.error' ).remove();
|
||||
|
||||
$notificationDialog.find( 'h3' ).after( '<div class="error">' + message + '</div>' );
|
||||
};
|
||||
|
||||
/**
|
||||
* Send an Ajax request to the server to install a plugin.
|
||||
|
@ -216,14 +281,19 @@ window.wp = window.wp || {};
|
|||
wp.updates.updateLock = true;
|
||||
|
||||
var data = {
|
||||
'_ajax_nonce': wp.updates.ajaxNonce,
|
||||
'slug': slug
|
||||
_ajax_nonce: wp.updates.ajaxNonce,
|
||||
slug: slug,
|
||||
username: wp.updates.filesystemCredentials.ftp.username,
|
||||
password: wp.updates.filesystemCredentials.ftp.password,
|
||||
hostname: wp.updates.filesystemCredentials.ftp.hostname,
|
||||
connection_type: wp.updates.filesystemCredentials.ftp.connectionType,
|
||||
public_key: wp.updates.filesystemCredentials.ssh.publicKey,
|
||||
private_key: wp.updates.filesystemCredentials.ssh.privateKey
|
||||
};
|
||||
|
||||
wp.ajax.post( 'install-plugin', data )
|
||||
.done( wp.updates.installSuccess )
|
||||
.fail( wp.updates.installError )
|
||||
.always( wp.updates.updateAlways );
|
||||
.fail( wp.updates.installError );
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -239,6 +309,14 @@ window.wp = window.wp || {};
|
|||
$message.removeClass( 'updating-message' ).addClass( 'updated-message button-disabled' );
|
||||
$message.text( wp.updates.l10n.installed );
|
||||
wp.a11y.speak( wp.updates.l10n.installedMsg );
|
||||
wp.updates.updateDoneSuccessfully = true;
|
||||
|
||||
/*
|
||||
* The lock can be released since the update was successful,
|
||||
* and any other updates can commence.
|
||||
*/
|
||||
wp.updates.updateLock = false;
|
||||
wp.updates.queueChecker();
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -250,11 +328,36 @@ window.wp = window.wp || {};
|
|||
*/
|
||||
wp.updates.installError = function( response ) {
|
||||
var $message = $( '.plugin-card-' + response.slug ).find( '.install-now' );
|
||||
wp.updates.updateDoneSuccessfully = false;
|
||||
if ( response.errorCode && response.errorCode == 'unable_to_connect_to_filesystem' ) {
|
||||
wp.updates.credentialError( response, 'install-plugin' );
|
||||
return;
|
||||
}
|
||||
|
||||
$message.removeClass( 'updating-message' );
|
||||
$message.text( wp.updates.l10n.installNow );
|
||||
|
||||
wp.updates.updateLock = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Events that need to happen when there is a credential error
|
||||
*
|
||||
* @since 4.2.0
|
||||
*/
|
||||
wp.updates.credentialError = function( response, type ) {
|
||||
wp.updates.updateQueue.push( {
|
||||
'type': type,
|
||||
'data': {
|
||||
// Not cool that we're depending on response for this data.
|
||||
// This would feel more whole in a view all tied together.
|
||||
plugin: response.plugin,
|
||||
slug: response.slug
|
||||
}
|
||||
} );
|
||||
wp.updates.showErrorInCredentialsForm( response.error );
|
||||
wp.updates.requestFilesystemCredentials();
|
||||
};
|
||||
|
||||
/**
|
||||
* If an install/update job has been placed in the queue, queueChecker pulls it out and runs it.
|
||||
|
@ -282,9 +385,55 @@ window.wp = window.wp || {};
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Request the users filesystem credentials if we don't have them already
|
||||
*
|
||||
* @since 4.2.0
|
||||
*/
|
||||
wp.updates.requestFilesystemCredentials = function() {
|
||||
if ( wp.updates.updateDoneSuccessfully === false ) {
|
||||
wp.updates.updateLock = true;
|
||||
$( 'body' ).addClass( 'modal-open' );
|
||||
$( '#request-filesystem-credentials-dialog' ).show();
|
||||
}
|
||||
};
|
||||
|
||||
$( document ).ready( function() {
|
||||
/*
|
||||
* Check whether a user needs to submit filesystem credentials based on whether
|
||||
* the form was output on the page server-side.
|
||||
*
|
||||
* @see {wp_print_request_filesystem_credentials_modal() in PHP}
|
||||
*/
|
||||
wp.updates.shouldRequestFilesystemCredentials = ( $( '#request-filesystem-credentials-dialog' ).length <= 0 ) ? false : true;
|
||||
|
||||
// File system credentials form submit noop-er / handler.
|
||||
$( '#request-filesystem-credentials-dialog form' ).on( 'submit', function() {
|
||||
// Persist the credentials input by the user for the duration of the page load.
|
||||
wp.updates.filesystemCredentials.ftp.hostname = $('#hostname').val();
|
||||
wp.updates.filesystemCredentials.ftp.username = $('#username').val();
|
||||
wp.updates.filesystemCredentials.ftp.password = $('#password').val();
|
||||
wp.updates.filesystemCredentials.ftp.connectionType = $('input[name="connection_type"]:checked').val();
|
||||
wp.updates.filesystemCredentials.ssh.publicKey = $('#public_key').val();
|
||||
wp.updates.filesystemCredentials.ssh.privateKey = $('#private_key').val();
|
||||
|
||||
$( '#request-filesystem-credentials-dialog' ).hide();
|
||||
$( 'body' ).removeClass( 'modal-open' );
|
||||
|
||||
// Unlock and invoke the queue.
|
||||
wp.updates.updateLock = false;
|
||||
wp.updates.queueChecker();
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
// Click handler for plugin updates in List Table view.
|
||||
$( '.plugin-update-tr .update-link' ).on( 'click', function( e ) {
|
||||
e.preventDefault();
|
||||
if ( wp.updates.shouldRequestFilesystemCredentials && ! wp.updates.updateLock ) {
|
||||
wp.updates.requestFilesystemCredentials();
|
||||
}
|
||||
var $row = $( e.target ).parents( '.plugin-update-tr' );
|
||||
wp.updates.updatePlugin( $row.data( 'plugin' ), $row.data( 'slug' ) );
|
||||
} );
|
||||
|
@ -315,6 +464,9 @@ window.wp = window.wp || {};
|
|||
|
||||
$( '.plugin-card .install-now' ).on( 'click', function( e ) {
|
||||
e.preventDefault();
|
||||
if ( wp.updates.shouldRequestFilesystemCredentials && ! wp.updates.updateLock ) {
|
||||
wp.updates.requestFilesystemCredentials();
|
||||
}
|
||||
var $button = $( e.target );
|
||||
if ( $button.hasClass( 'button-disabled' ) ) {
|
||||
return;
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -128,7 +128,10 @@ if ( $tab !== 'upload' ) {
|
|||
*/
|
||||
do_action( "install_plugins_$tab", $paged ); ?>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
wp_print_request_filesystem_credentials_modal();
|
||||
|
||||
/**
|
||||
* WordPress Administration Template Footer.
|
||||
*/
|
||||
|
|
|
@ -476,4 +476,6 @@ do_action( 'pre_current_active_plugins', $plugins['all'] );
|
|||
</div>
|
||||
|
||||
<?php
|
||||
wp_print_request_filesystem_credentials_modal();
|
||||
|
||||
include(ABSPATH . 'wp-admin/admin-footer.php');
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* @global string $wp_version
|
||||
*/
|
||||
$wp_version = '4.2-beta1-31810';
|
||||
$wp_version = '4.2-beta1-31811';
|
||||
|
||||
/**
|
||||
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.
|
||||
|
|
Loading…
Reference in New Issue