WordPress.org

Make WordPress Core

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

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

Work in progress for AJAX theme install, to show where I'm going with this, and discuss. Screenshots: https://cloudup.com/cYjd7oIeDp7

  • 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        '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        include_once( ABSPATH . 'wp-admin/includes/theme-install.php' );
     2991
     2992        $api = themes_api( 'theme_information', array(
     2993                'slug'   => sanitize_key( $_POST['slug'] ),
     2994                'fields' => array( 'sections' => false )
     2995        ) );
     2996
     2997        if ( is_wp_error( $api ) ) {
     2998                $status['error'] = $api->get_error_message();
     2999                wp_send_json_error( $status );
     3000        }
     3001
     3002        $upgrader = new Theme_Upgrader( new Automatic_Upgrader_Skin() );
     3003        $result = $upgrader->install( $api->download_link );
     3004
     3005        if ( is_wp_error( $result ) ) {
     3006                $status['error'] = $result->get_error_message();
     3007                wp_send_json_error( $status );
     3008        }
     3009
     3010        // Never switch to theme (unlike plugin activation)
     3011        // Backbone should then also show the "Already installed banner"
     3012
     3013        wp_send_json_success( $status );
     3014}
     3015
     3016/**
    29713017 * AJAX handler for saving a post from Ptrss This.
    29723018 *
    29733019 * @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

     
    257257
    258258
    259259        /**
     260         * Send an Ajax request to the server to install a theme.
     261         *
     262         * @since 4.2.0
     263         *
     264         * @param {string} slug
     265         */
     266        wp.updates.installTheme = function( slug ) {
     267                var $message = $( '#theme-' + slug ).find( '.theme-install' );
     268
     269                $message.addClass( 'updating-message' );
     270                $message.text( wp.updates.l10n.installing );
     271                wp.a11y.speak( wp.updates.l10n.installingMsg );
     272
     273                if ( wp.updates.updateLock ) {
     274                        wp.updates.updateQueue.push( {
     275                                type: 'install-theme',
     276                                data: {
     277                                        slug: slug
     278                                }
     279                        } );
     280                        return;
     281                }
     282
     283                wp.updates.updateLock = true;
     284
     285                var data = {
     286                        '_ajax_nonce': wp.updates.ajaxNonce,
     287                        'slug':        slug
     288                };
     289
     290                wp.ajax.post( 'install-theme', data )
     291                        .done( wp.updates.installThemeSuccess )
     292                        .fail( wp.updates.installThemeError )
     293                        .always( wp.updates.updateAlways );
     294        };
     295
     296        /**
     297         * On theme install success, update the UI with the result.
     298         *
     299         * @since 4.2.0
     300         *
     301         * @param {object} response
     302         */
     303        wp.updates.installThemeSuccess = function( response ) {
     304                var $card = $( '#theme-' + response.slug ),
     305                        $message = $card.find( '.theme-install' );
     306
     307                $message.removeClass( 'updating-message' ).addClass( 'updated-message button-disabled' );
     308                $message.text( wp.updates.l10n.installed );
     309                wp.a11y.speak( wp.updates.l10n.installedMsg );
     310                $card.addClass( 'is-installed' );
     311        };
     312
     313        /**
     314         * On theme install failure, update the UI appropriately.
     315         *
     316         * @since 4.2.0
     317         *
     318         * @param {object} response
     319         */
     320        wp.updates.installThemeError = function( response ) {
     321                var $message = $( '#theme-' + response.slug ).find( '.theme-install' );
     322
     323                $message.removeClass( 'updating-message' );
     324                $message.text( wp.updates.l10n.installNow );
     325        };
     326
     327
     328        /**
    260329         * If an install/update job has been placed in the queue, queueChecker pulls it out and runs it.
    261330         *
    262331         * @since 4.2.0
  • 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

     
    210210        $aria_action = esc_attr( $theme['id'] . '-action' );
    211211        $aria_name   = esc_attr( $theme['id'] . '-name' );
    212212        ?>
    213 <div class="theme<?php if ( $theme['active'] ) echo ' active'; ?>" tabindex="0" aria-describedby="<?php echo $aria_action . ' ' . $aria_name; ?>">
     213<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; ?>">
    214214        <?php if ( ! empty( $theme['screenshot'][0] ) ) { ?>
    215215                <div class="theme-screenshot">
    216216                        <img src="<?php echo $theme['screenshot'][0]; ?>" alt="" />