Make WordPress Core

Changeset 31749


Ignore:
Timestamp:
03/12/2015 08:52:42 AM (12 years ago)
Author:
jorbin
Message:

Request FTP and SSH credentials when needed during shiny updates

This is a first pass at requesting FTP and SSH credentials when needed during shiny updates. Styling and some UX improvements are still needed, but we do show the prompt and use the passed data when doing plugin installs and updates for shiny updates. There are also a couple of areas that we could improve code wise such how we create the requestFilesystemCredentials part of the localized _wpUpdatesSettings. Over the past half century, we've split the atom, we've spliced the gene and we've roamed Tranquility Base. We've reached for the stars and never have we been closer to having them in our grasp. That has nothing to do with shiny updates.

Props ericlewis, jorbin, and drewapicture for testing
Fixes #31528

Location:
trunk/src
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/css/forms.css

    r31611 r31749  
    851851}
    852852
     853/*------------------------------------------------------------------------------
     854   Credentials check dialog for Install and Updates
     855------------------------------------------------------------------------------*/
     856
     857.request-filesystem-credentials-dialog {
     858        display: none;
     859}
     860
     861.request-filesystem-credentials-dialog .notification-dialog{
     862        top: 15%
     863}
     864
     865.request-filesystem-credentials-dialog-content{
     866        margin: 25px;
     867}
     868.request-filesystem-credentials-dialog-content input[type="text"],
     869.request-filesystem-credentials-dialog-content input[type="password"]{
     870        width:85%;
     871}
     872
    853873/* =Media Queries
    854874-------------------------------------------------------------- */
  • trunk/src/wp-admin/includes/ajax-actions.php

    r31645 r31749  
    29142914                $status['error'] = $result->get_error_message();
    29152915                wp_send_json_error( $status );
     2916        } else if ( is_null( $result ) ) {
     2917                $status['errorCode'] = __( 'unable_to_connect_to_filesystem' );
     2918                $status['error'] = __( 'Unable to connect to the filesystem. Please confirm your credentials.' );
     2919                wp_send_json_error( $status );
    29162920        }
    29172921
    … …  
    29552959        $upgrader = new Plugin_Upgrader( new Automatic_Upgrader_Skin() );
    29562960        $result = $upgrader->bulk_upgrade( array( $plugin ) );
    2957 
    29582961        if ( is_array( $result ) ) {
    2959                 $result = $result[ $plugin ];
    2960         }
    2961 
    2962         if ( is_wp_error( $result ) ) {
     2962                wp_send_json_success( $status );
     2963        } else if ( is_wp_error( $result ) ) {
    29632964                $status['error'] = $result->get_error_message();
    29642965                wp_send_json_error( $status );
    2965         }
    2966 
    2967         wp_send_json_success( $status );
     2966        } else if ( is_bool( $result ) && ! $result ) {
     2967                $status['errorCode'] = __( 'unable_to_connect_to_filesystem' );
     2968                $status['error'] = __( 'Unable to connect to the filesystem. Please confirm your credentials.' );
     2969                wp_send_json_error( $status );
     2970        }
    29682971}
    29692972
  • trunk/src/wp-admin/js/updates.js

    r31594 r31749  
    2323
    2424        /**
     25         * Whether filesystem credentials need to be requested from the user.
     26         *
     27         * @since 4.2.0
     28         *
     29         * @var bool
     30         */
     31        wp.updates.shouldRequestFilesystemCredentials = window._wpUpdatesSettings.requestFilesystemCredentials;
     32
     33        /**
     34         * Filesystem credentials to be packaged along with the request.
     35         *
     36         * @since  4.2.0
     37         *
     38         * @var object
     39         */
     40        wp.updates.filesystemCredentials = {
     41                ftp: {
     42                        host: null,
     43                        username: null,
     44                        password: null,
     45                        connectionType: null
     46                },
     47                ssh: {
     48                        publicKey: null,
     49                        privateKey: null
     50                }
     51        };
     52
     53        /**
    2554         * Flag if we're waiting for an install/update to complete.
    2655         *
    … …  
    3059         */
    3160        wp.updates.updateLock = false;
     61
     62        /**
     63         * Flag if we've done an install or update successfully.
     64         *
     65         * @since 4.2.0
     66         *
     67         * @var bool
     68         */
     69        wp.updates.updateDoneSuccessfully = false;
    3270
    3371        /**
    … …  
    125163                var data = {
    126164                        '_ajax_nonce': wp.updates.ajaxNonce,
    127                         'plugin':      plugin,
    128                         'slug':        slug
     165                        'plugin':        plugin,
     166                        'slug':          slug,
     167                        username:        wp.updates.filesystemCredentials.ftp.username,
     168                        password:        wp.updates.filesystemCredentials.ftp.password,
     169                        hostname:        wp.updates.filesystemCredentials.ftp.hostname,
     170                        connection_type: wp.updates.filesystemCredentials.ftp.connectionType,
     171                        public_key:      wp.updates.filesystemCredentials.ssh.publicKey,
     172                        private_key:     wp.updates.filesystemCredentials.ssh.privateKey
    129173                };
    130174
    … …  
    158202
    159203                wp.updates.decrementCount( 'plugin' );
     204
     205                wp.updates.updateDoneSuccessfully = true;
    160206        };
    161207
    … …  
    169215        wp.updates.updateError = function( response ) {
    170216                var $message;
     217                wp.updates.updateDoneSuccessfully = false;
     218                if ( response.errorCode && response.errorCode == 'unable_to_connect_to_filesystem' ) {
     219                        wp.updates.credentialError( response, 'update-plugin' );
     220                        return;
     221                }
    171222                if ( 'plugins' === pagenow || 'plugins-network' === pagenow ) {
    172223                        $message = $( '#' + response.slug ).next().find( '.update-message' );
    … …  
    178229                wp.a11y.speak( wp.updates.l10n.updateFailed );
    179230        };
     231
     232        /**
     233         * Show an
     234         *
     235         * @param {string} message
     236         * @since 4.2.0
     237         */
     238        wp.updates.showErrorInCredentialsForm = function( message ) {
     239                var $notificationDialog = $( '.notification-dialog' );
     240
     241                // Remove any existing error
     242                $notificationDialog.find( '.error' ).remove();
     243
     244                $notificationDialog.find( 'h3' ).after( '<div class="error">' + message + '</div>' );
     245    };
    180246
    181247        /**
    … …  
    217283
    218284                var data = {
    219                         '_ajax_nonce': wp.updates.ajaxNonce,
    220                         'slug':        slug
     285                        '_ajax_nonce':     wp.updates.ajaxNonce,
     286                        'slug':            slug,
     287                        'username':        wp.updates.filesystemCredentials.ftp.username,
     288                        'password':        wp.updates.filesystemCredentials.ftp.password,
     289                        'hostname':        wp.updates.filesystemCredentials.ftp.hostname,
     290                        'connection_type': wp.updates.filesystemCredentials.ftp.connectionType,
     291                        'public_key':      wp.updates.filesystemCredentials.ssh.publicKey,
     292                        'private_key':     wp.updates.filesystemCredentials.ssh.privateKey
    221293                };
    222294
    … …  
    240312                $message.text( wp.updates.l10n.installed );
    241313                wp.a11y.speak( wp.updates.l10n.installedMsg );
     314                wp.updates.updateDoneSuccessfully = true;
    242315        };
    243316
    … …  
    251324        wp.updates.installError = function( response ) {
    252325                var $message = $( '.plugin-card-' + response.slug ).find( '.install-now' );
     326                wp.updates.updateDoneSuccessfully = false;
     327                if ( response.errorCode && response.errorCode == 'unable_to_connect_to_filesystem' ) {
     328                        wp.updates.credentialError( response, 'update-plugin' );
     329                        return;
     330                }
    253331
    254332                $message.removeClass( 'updating-message' );
    255333                $message.text( wp.updates.l10n.installNow );
     334        };
     335
     336        /**
     337         * Events that need to happen when there is a credential error
     338         *
     339         * @since 4.2.0
     340         */
     341        wp.updates.credentialError = function( response, type ) {
     342                wp.updates.updateQueue.push( {
     343                        'type': type,
     344                        'data': {
     345                                // Not cool that we're depending on response for this data.
     346                                // This would feel more whole in a view all tied together.
     347                                plugin: response.plugin,
     348                                slug: response.slug
     349                        }
     350                } );
     351                wp.updates.showErrorInCredentialsForm( response.error );
     352                wp.updates.requestFilesystemCredentials();
    256353        };
    257354
    … …  
    282379                }
    283380        };
    284 
     381        /**
     382         * Request the users filesystem credentials if we don't have them already
     383         *
     384         * @since 4.2.0
     385         */
     386        wp.updates.requestFilesystemCredentials = function() {
     387                if ( wp.updates.updateDoneSuccessfully === false ) {
     388                        wp.updates.updateLock = true;
     389                        $('#request-filesystem-credentials-dialog').show();
     390                }
     391        };
     392
     393        // Bind various click handlers.
    285394        $( document ).ready( function() {
     395                // File system credentials form submit noop-er / handler.
     396                $('#request-filesystem-credentials-dialog form').on( 'submit', function() {
     397                        // Persist the credentials input by the user for the duration of the page load.
     398                        wp.updates.filesystemCredentials.ftp.hostname = $('#hostname').val();
     399                        wp.updates.filesystemCredentials.ftp.username = $('#username').val();
     400                        wp.updates.filesystemCredentials.ftp.password = $('#password').val();
     401                        wp.updates.filesystemCredentials.ftp.connectionType = $('input[name="connection_type"]:checked').val();
     402                        wp.updates.filesystemCredentials.ssh.publicKey = $('#public_key').val();
     403                        wp.updates.filesystemCredentials.ssh.privateKey = $('#private_key').val();
     404
     405                        $('#request-filesystem-credentials-dialog').hide();
     406
     407                        // Unlock and invoke the queue.
     408                        wp.updates.updateLock = false;
     409                        wp.updates.queueChecker();
     410
     411                        return false;
     412                });
     413
     414                // Click handler for plugin updates in List Table view.
    286415                $( '.plugin-update-tr .update-link' ).on( 'click', function( e ) {
    287416                        e.preventDefault();
     417                        if ( wp.updates.shouldRequestFilesystemCredentials === '1' && ! wp.updates.updateLock ) {
     418                                wp.updates.requestFilesystemCredentials();
     419                        }
    288420                        var $row = $( e.target ).parents( '.plugin-update-tr' );
    289421                        wp.updates.updatePlugin( $row.data( 'plugin' ), $row.data( 'slug' ) );
    … …  
    316448                $( '.plugin-card .install-now' ).on( 'click', function( e ) {
    317449                        e.preventDefault();
     450                        if ( wp.updates.shouldRequestFilesystemCredentials === '1' && ! wp.updates.updateLock ) {
     451                                wp.updates.requestFilesystemCredentials();
     452                        }
     453
    318454                        var $button = $( e.target );
    319455                        if ( $button.hasClass( 'button-disabled' ) ) {
  • trunk/src/wp-admin/plugin-install.php

    r31333 r31749  
    129129do_action( "install_plugins_$tab", $paged ); ?>
    130130</div>
     131
     132<div id="request-filesystem-credentials-dialog" class="notification-dialog-wrap request-filesystem-credentials-dialog">
     133        <div class="notification-dialog-background"></div>
     134        <div class="notification-dialog">
     135                <div class="request-filesystem-credentials-dialog-content">
     136                        <?php request_filesystem_credentials( site_url() ); ?>
     137                <div>
     138        </div>
     139</div>
     140
    131141<?php
    132142/**
  • trunk/src/wp-admin/plugins.php

    r31696 r31749  
    476476</div>
    477477
     478<div id="request-filesystem-credentials-dialog" class="notification-dialog-wrap request-filesystem-credentials-dialog">
     479        <div class="notification-dialog-background"></div>
     480        <div class="notification-dialog">
     481                <div class="request-filesystem-credentials-dialog-content">
     482                        <?php request_filesystem_credentials( site_url() ); ?>
     483                <div>
     484        </div>
     485</div>
    478486<?php
    479487include(ABSPATH . 'wp-admin/admin-footer.php');
  • trunk/src/wp-includes/script-loader.php

    r31746 r31749  
    543543
    544544                $scripts->add( 'updates', "/wp-admin/js/updates$suffix.js", array( 'jquery', 'wp-util', 'wp-a11y' ) );
     545
     546                /*
     547                 * Determine whether the user will need to enter filesystem credentials
     548                 * on the front-end.
     549                 */
     550                require_once(ABSPATH . 'wp-admin/includes/file.php');
     551                $filesystem_method = get_filesystem_method();
     552                ob_start();
     553                $filesystem_credentials_are_stored = request_filesystem_credentials( self_admin_url() );
     554                ob_end_clean();
     555                $request_filesystem_credentials = ( $filesystem_method != 'direct' && ! $filesystem_credentials_are_stored ) ? 1 : 0;
     556
    545557                did_action( 'init' ) && $scripts->localize( 'updates', '_wpUpdatesSettings', array(
    546558                        'ajax_nonce' => wp_create_nonce( 'updates' ),
     559                        'requestFilesystemCredentials' => $request_filesystem_credentials,
    547560                        'l10n'       => array(
    548561                                'updating'      => __( 'Updating...' ),
Note: See TracChangeset for help on using the changeset viewer.