WordPress.org

Make WordPress Core

Ticket #31530: 31530-theme-install-and-update-workinprogress.diff

File 31530-theme-install-and-update-workinprogress.diff, 14.0 KB (added by stephdau, 6 years ago)

Continuation of 31530-theme-install-workinprogress.diff, starting to add update functionality. Not as easy as install, see upcoming comment.

  • src/wp-admin/admin-ajax.php

     
    6161        'query-attachments', 'save-attachment', 'save-attachment-compat', 'send-link-to-editor',
    6262        'send-attachment-to-editor', 'save-attachment-order', 'heartbeat', 'get-revision-diffs',
    6363        'save-user-color-scheme', 'update-widget', 'query-themes', 'parse-embed', 'set-attachment-thumbnail',
    64         'parse-media-shortcode', 'destroy-sessions', 'install-plugin', 'update-plugin', 'press-this-save-post',
    65         'press-this-add-category',
     64        'parse-media-shortcode', 'destroy-sessions', 'install-plugin', 'update-plugin', 'install-theme',
     65        'update-theme', 'press-this-save-post', 'press-this-add-category',
    6666);
    6767
    6868// Register core Ajax calls.
  • src/wp-admin/includes/ajax-actions.php

     
    29682968}
    29692969
    29702970/**
     2971 * AJAX handler for installing a theme.
     2972 *
     2973 * @since 4.2.0
     2974 */
     2975function wp_ajax_install_theme() {
     2976        $status = array(
     2977                'install' => 'theme',
     2978                'slug'    => sanitize_key( $_POST['slug'] ),
     2979        );
     2980
     2981        if ( ! current_user_can( 'install_themes' ) ) {
     2982                $status['error'] = __( 'You do not have sufficient permissions to install themes on this site.' );
     2983                wp_send_json_error( $status );
     2984        }
     2985
     2986        check_ajax_referer( 'updates' );
     2987
     2988        include_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
     2989        include_once( ABSPATH . 'wp-admin/includes/theme.php' );
     2990
     2991        $api = themes_api( 'theme_information', array(
     2992                'slug'   => $status['slug'],
     2993                'fields' => array( 'sections' => false )
     2994        ) );
     2995
     2996        if ( is_wp_error( $api ) ) {
     2997                $status['error'] = $api->get_error_message();
     2998                wp_send_json_error( $status );
     2999        }
     3000
     3001        $upgrader = new Theme_Upgrader( new Automatic_Upgrader_Skin() );
     3002        $result = $upgrader->install( $api->download_link );
     3003
     3004        if ( is_wp_error( $result ) ) {
     3005                $status['error'] = $result->get_error_message();
     3006                wp_send_json_error( $status );
     3007        }
     3008
     3009        // Never switch to theme (unlike plugin activation).
     3010        // See WP_Theme_Install_List_Table::_get_theme_status() if we wanted to check on post-install status.
     3011
     3012        wp_send_json_success( $status );
     3013}
     3014
     3015/**
     3016 * AJAX handler for updating a theme.
     3017 *
     3018 * @since 4.2.0
     3019 */
     3020function wp_ajax_update_theme() {
     3021        $status = array(
     3022                'update' => 'theme',
     3023                'slug'   => sanitize_key( $_POST['slug'] ),
     3024        );
     3025
     3026        if ( ! current_user_can( 'update_themes' ) ) {
     3027                $status['error'] = __( 'You do not have sufficient permissions to update themes on this site.' );
     3028                wp_send_json_error( $status );
     3029        }
     3030
     3031        check_ajax_referer( 'updates' );
     3032
     3033        include_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
     3034
     3035        $current = get_site_transient( 'update_themes' );
     3036        if ( empty( $current ) ) {
     3037                wp_update_themes();
     3038        }
     3039
     3040        $upgrader = new Theme_Upgrader( new Automatic_Upgrader_Skin() );
     3041        $result = $upgrader->bulk_upgrade( array( $status['slug'] ) );
     3042
     3043        if ( is_array( $result ) ) {
     3044                $result = $result[ $status['slug'] ];
     3045        }
     3046
     3047        if ( is_wp_error( $result ) ) {
     3048                $status['error'] = $result->get_error_message();
     3049                wp_send_json_error( $status );
     3050        }
     3051
     3052        wp_send_json_success( $status );
     3053}
     3054
     3055/**
    29713056 * AJAX handler for saving a post from Ptrss This.
    29723057 *
    29733058 * @since 4.2.0
  • src/wp-admin/js/theme.js

     
    384384        render: function() {
    385385                var data = this.model.toJSON();
    386386                // Render themes using the html template
    387                 this.$el.html( this.html( data ) ).attr({
     387                this.$el.attr(
     388                        'id', 'theme-' + data.id
     389                ).html( this.html( data ) ).attr({
    388390                        tabindex: 0,
    389391                        'aria-describedby' : data.id + '-action ' + data.id + '-name'
    390392                });
     
    452454
    453455        preview: function( event ) {
    454456                var self = this,
     457                        $currentTarget = $( event.currentTarget ),
    455458                        current, preview;
    456459
    457460                // Bail if the user scrolled on a touch device
     
    459462                        return this.touchDrag = false;
    460463                }
    461464
    462                 // Allow direct link path to installing a theme.
    463                 if ( $( event.target ).hasClass( 'button-primary' ) ) {
     465                // Allow AJAX install of themes.
     466                if ( ! $currentTarget.hasClass( 'is-installed' ) && $( event.target ).hasClass( 'theme-install' ) && wp && wp.updates ) {
     467                        event.preventDefault();
     468                        wp.updates.installTheme( $currentTarget.attr( 'id' ).replace( /^theme-/,'' ) );
    464469                        return;
    465470                }
    466471
  • src/wp-admin/js/updates.js

     
    129129                };
    130130
    131131                wp.ajax.post( 'update-plugin', data )
    132                         .done( wp.updates.updateSuccess )
    133                         .fail( wp.updates.updateError )
     132                        .done( wp.updates.updatePluginSuccess )
     133                        .fail( wp.updates.updatePluginError )
    134134                        .always( wp.updates.updateAlways );
    135135        };
    136136
     
    141141         *
    142142         * @param {object} response
    143143         */
    144         wp.updates.updateSuccess = function( response ) {
     144        wp.updates.updatePluginSuccess = function( response ) {
    145145                var $message;
    146146                if ( 'plugins' === pagenow || 'plugins-network' === pagenow ) {
    147147                        $message = $( '#' + response.slug ).next().find( '.update-message' );
     
    166166         *
    167167         * @param {object} response
    168168         */
    169         wp.updates.updateError = function( response ) {
     169        wp.updates.updatePluginError = function( response ) {
    170170                var $message;
    171171                if ( 'plugins' === pagenow || 'plugins-network' === pagenow ) {
    172172                        $message = $( '#' + response.slug ).next().find( '.update-message' );
     
    221221                };
    222222
    223223                wp.ajax.post( 'install-plugin', data )
    224                         .done( wp.updates.installSuccess )
    225                         .fail( wp.updates.installError )
     224                        .done( wp.updates.installPluginSuccess )
     225                        .fail( wp.updates.installPluginError )
    226226                        .always( wp.updates.updateAlways );
    227227        };
    228228
     
    233233         *
    234234         * @param {object} response
    235235         */
    236         wp.updates.installSuccess = function( response ) {
     236        wp.updates.installPluginSuccess = function( response ) {
    237237                var $message = $( '.plugin-card-' + response.slug ).find( '.install-now' );
    238238
    239239                $message.removeClass( 'updating-message' ).addClass( 'updated-message button-disabled' );
     
    248248         *
    249249         * @param {object} response
    250250         */
    251         wp.updates.installError = function( response ) {
     251        wp.updates.installPluginError = function( response ) {
    252252                var $message = $( '.plugin-card-' + response.slug ).find( '.install-now' );
    253253
    254254                $message.removeClass( 'updating-message' );
     
    255255                $message.text( wp.updates.l10n.installNow );
    256256        };
    257257
     258        /**
     259         * Send an Ajax request to the server to update a theme.
     260         *
     261         * @since 4.2.0
     262         *
     263         * @param {string} theme
     264         * @param {string} slug
     265         */
     266        wp.updates.updateTheme = function( theme, slug ) {
     267                var $message = $( '#theme-' + slug ).find( '.theme-update' );
    258268
     269                $message.addClass( 'updating-message' );
     270                $message.text( wp.updates.l10n.updating );
     271                wp.a11y.speak( wp.updates.l10n.updatingMsg );
     272
     273                if ( wp.updates.updateLock ) {
     274                        wp.updates.updateQueue.push( {
     275                                type: 'update-theme',
     276                                data: {
     277                                        theme: theme,
     278                                        slug: slug
     279                                }
     280                        } );
     281                        return;
     282                }
     283
     284                wp.updates.updateLock = true;
     285
     286                var data = {
     287                        '_ajax_nonce': wp.updates.ajaxNonce,
     288                        'theme':       theme,
     289                        'slug':        slug
     290                };
     291
     292                wp.ajax.post( 'update-theme', data )
     293                        .done( wp.updates.updateThemeSuccess )
     294                        .fail( wp.updates.updateThemeError )
     295                        .always( wp.updates.updateAlways );
     296        };
     297
    259298        /**
     299         * On a successful theme update, update the UI with the result.
     300         *
     301         * @since 4.2.0
     302         *
     303         * @param {object} response
     304         */
     305        wp.updates.updateThemeSuccess = function( response ) {
     306                var $message = $( '#theme-' + response.slug ).find( '.theme-update' );
     307
     308                $message.removeClass( 'updating-message' ).addClass( 'updated-message button-disabled' );
     309                $message.text( wp.updates.l10n.updated );
     310                wp.a11y.speak( wp.updates.l10n.updatedMsg );
     311
     312                wp.updates.decrementCount( 'theme' );
     313        };
     314
     315        /**
     316         * On a theme update error, update the UI appropriately.
     317         *
     318         * @since 4.2.0
     319         *
     320         * @param {object} response
     321         */
     322        wp.updates.updateThemeError = function( response ) {
     323                var $message = $( '#theme-' + response.slug ).find( '.theme-update' );
     324
     325                $message.removeClass( 'updating-message' );
     326                $message.text( wp.updates.l10n.updateFailed );
     327                wp.a11y.speak( wp.updates.l10n.updateFailed );
     328        };
     329
     330        /**
     331         * Send an Ajax request to the server to install a theme.
     332         *
     333         * @since 4.2.0
     334         *
     335         * @param {string} slug
     336         */
     337        wp.updates.installTheme = function( slug ) {
     338                var $message = $( '#theme-' + slug ).find( '.theme-install' );
     339
     340                $message.addClass( 'updating-message' );
     341                $message.text( wp.updates.l10n.installing );
     342                wp.a11y.speak( wp.updates.l10n.installingMsg );
     343
     344                if ( wp.updates.updateLock ) {
     345                        wp.updates.updateQueue.push( {
     346                                type: 'install-theme',
     347                                data: {
     348                                        slug: slug
     349                                }
     350                        } );
     351                        return;
     352                }
     353
     354                wp.updates.updateLock = true;
     355
     356                var data = {
     357                        '_ajax_nonce': wp.updates.ajaxNonce,
     358                        'slug':        slug
     359                };
     360
     361                wp.ajax.post( 'install-theme', data )
     362                        .done( wp.updates.installThemeSuccess )
     363                        .fail( wp.updates.installThemeError )
     364                        .always( wp.updates.updateAlways );
     365        };
     366
     367        /**
     368         * On theme install success, update the UI with the result.
     369         *
     370         * @since 4.2.0
     371         *
     372         * @param {object} response
     373         */
     374        wp.updates.installThemeSuccess = function( response ) {
     375                var $card = $( '#theme-' + response.slug ),
     376                        $message = $card.find( '.theme-install' );
     377
     378                $message.removeClass( 'updating-message' ).addClass( 'updated-message button-disabled' );
     379                $message.text( wp.updates.l10n.installed );
     380                wp.a11y.speak( wp.updates.l10n.installedMsg );
     381                $card.addClass( 'is-installed' ); // Hides the button, should show banner
     382        };
     383
     384        /**
     385         * On theme install failure, update the UI appropriately.
     386         *
     387         * @since 4.2.0
     388         *
     389         * @param {object} response
     390         */
     391        wp.updates.installThemeError = function( response ) {
     392                var $message = $( '#theme-' + response.slug ).find( '.theme-install' );
     393
     394                $message.removeClass( 'updating-message' );
     395                $message.text( wp.updates.l10n.installNow );
     396        };
     397
     398
     399        /**
    260400         * If an install/update job has been placed in the queue, queueChecker pulls it out and runs it.
    261401         *
    262402         * @since 4.2.0
     
    275415                        case 'install-plugin':
    276416                                wp.updates.installPlugin( job.data.slug );
    277417                                break;
     418                        case 'update-theme':
     419                                wp.updates.updateTheme( job.data.theme, job.data.slug );
     420                                break;
     421                        case 'install-theme':
     422                                wp.updates.installTheme( job.data.slug );
     423                                break;
    278424                        default:
    279425                                window.console.log( 'Failed to exect queued update job.' );
    280426                                window.console.log( job );
  • src/wp-admin/theme-install.php

     
    5555
    5656wp_enqueue_script( 'theme' );
    5757
     58wp_enqueue_script( 'updates' );
     59
    5860if ( $tab ) {
    5961        /**
    6062         * Fires before each of the tabs are rendered on the Install Themes page.
     
    204206        <h3 class="theme-name">{{ data.name }}</h3>
    205207
    206208        <div class="theme-actions">
    207                 <a class="button button-primary" href="{{ data.install_url }}"><?php esc_html_e( 'Install' ); ?></a>
     209                <a class="button button-primary theme-install" href="{{ data.install_url }}"><?php esc_html_e( 'Install' ); ?></a>
    208210                <a class="button button-secondary preview install-theme-preview" href="#"><?php esc_html_e( 'Preview' ); ?></a>
    209211        </div>
    210212
  • src/wp-admin/themes.php

     
    117117wp_enqueue_script( 'theme' );
    118118wp_enqueue_script( 'customize-loader' );
    119119
     120wp_enqueue_script( 'updates' );
     121
    120122require_once( ABSPATH . 'wp-admin/admin-header.php' );
    121123?>
    122124
     
    210212        $aria_action = esc_attr( $theme['id'] . '-action' );
    211213        $aria_name   = esc_attr( $theme['id'] . '-name' );
    212214        ?>
    213 <div class="theme<?php if ( $theme['active'] ) echo ' active'; ?>" tabindex="0" aria-describedby="<?php echo $aria_action . ' ' . $aria_name; ?>">
     215<div id="theme-<?php echo esc_attr( $theme['id'] ); ?>" class="theme<?php if ( $theme['active'] ) echo ' active'; ?>" tabindex="0" aria-describedby="<?php echo $aria_action . ' ' . $aria_name; ?>">
    214216        <?php if ( ! empty( $theme['screenshot'][0] ) ) { ?>
    215217                <div class="theme-screenshot">
    216218                        <img src="<?php echo $theme['screenshot'][0]; ?>" alt="" />
     
    234236                        <a class="button button-primary customize load-customize hide-if-no-customize" href="<?php echo $theme['actions']['customize']; ?>"><?php _e( 'Customize' ); ?></a>
    235237                <?php } ?>
    236238        <?php } else { ?>
     239                <?php if ( $theme['hasUpdate'] ) { ?>
     240                        <a class="button button-secondary theme-update" href="<?php echo $theme['actions']['activate']; ?>"><?php _e( 'Update Now' ); ?></a>
     241                <?php } ?>
    237242                <a class="button button-secondary activate" href="<?php echo $theme['actions']['activate']; ?>"><?php _e( 'Activate' ); ?></a>
    238243                <?php if ( current_user_can( 'edit_theme_options' ) && current_user_can( 'customize' ) ) { ?>
    239244                        <a class="button button-primary load-customize hide-if-no-customize" href="<?php echo $theme['actions']['customize']; ?>"><?php _e( 'Live Preview' ); ?></a>
     
    331336                        <a class="button button-primary customize load-customize hide-if-no-customize" href="{{ data.actions.customize }}"><?php _e( 'Customize' ); ?></a>
    332337                <# } #>
    333338        <# } else { #>
     339                <# if ( data.hasUpdate ) { #>
     340                        <a class="button button-secondary theme-update" href="{{{ data.actions.activate }}}"><?php _e( 'Update Now' ); ?></a>
     341                <# } #>
    334342                <a class="button button-secondary activate" href="{{{ data.actions.activate }}}"><?php _e( 'Activate' ); ?></a>
    335343                <a class="button button-primary load-customize hide-if-no-customize" href="{{{ data.actions.customize }}}"><?php _e( 'Live Preview' ); ?></a>
    336344                <a class="button button-secondary hide-if-customize" href="{{{ data.actions.preview }}}"><?php _e( 'Preview' ); ?></a>