WordPress.org

Make WordPress Core


Ignore:
Timestamp:
06/15/2016 04:36:07 PM (3 years ago)
Author:
obenland
Message:

Update/Install: Shiny Updates v2.

Gone are the days of isolation and feelings of "meh", brought on by The Bleak Screen of Sadness. For a shiny knight has arrived to usher our plugins and themes along their arduous journey of installation, updates, and the inevitable fate of ultimate deletion.

Props swissspidy, adamsilverstein, mapk, afragen, ocean90, ryelle, j-falk, michael-arestad, melchoyce, DrewAPicture, AdamSoucie, ethitter, pento, dd32, kraftbj, Ipstenu, jorbin, afercia, stephdau, paulwilde, jipmoors, khag7, svovaf, jipmoors, obenland.
Fixes #22029, #25828, #31002, #31529, #31530, #31773, #33637, #35032.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/includes/ajax-actions.php

    r37674 r37714  
    28622862        ), $update_php );
    28632863
     2864        if ( current_user_can( 'switch_themes' ) ) {
     2865            if ( is_multisite() ) {
     2866                $theme->activate_url = add_query_arg( array(
     2867                    'action'   => 'enable',
     2868                    '_wpnonce' => wp_create_nonce( 'enable-theme_' . $theme->slug ),
     2869                    'theme'    => $theme->slug,
     2870                ), network_admin_url( 'themes.php' ) );
     2871            } else {
     2872                $theme->activate_url = add_query_arg( array(
     2873                    'action'     => 'activate',
     2874                    '_wpnonce'   => wp_create_nonce( 'switch-theme_' . $theme->slug ),
     2875                    'stylesheet' => $theme->slug,
     2876                ), admin_url( 'themes.php' ) );
     2877            }
     2878        }
     2879
     2880        if ( ! is_multisite() && current_user_can( 'edit_theme_options' ) && current_user_can( 'customize' ) ) {
     2881            $theme->customize_url = add_query_arg( array(
     2882                'return' => urlencode( network_admin_url( 'theme-install.php', 'relative' ) ),
     2883            ), wp_customize_url( $theme->slug ) );
     2884        }
     2885
    28642886        $theme->name        = wp_kses( $theme->name, $themes_allowedtags );
    28652887        $theme->author      = wp_kses( $theme->author, $themes_allowedtags );
     
    30683090
    30693091    wp_send_json_success( array( 'message' => $message ) );
    3070 }
    3071 
    3072 
    3073 /**
    3074  * AJAX handler for updating a plugin.
    3075  *
    3076  * @since 4.2.0
    3077  *
    3078  * @see Plugin_Upgrader
    3079  */
    3080 function wp_ajax_update_plugin() {
    3081     global $wp_filesystem;
    3082 
    3083     $plugin = urldecode( $_POST['plugin'] );
    3084 
    3085     $status = array(
    3086         'update'     => 'plugin',
    3087         'plugin'     => $plugin,
    3088         'slug'       => sanitize_key( $_POST['slug'] ),
    3089         'oldVersion' => '',
    3090         'newVersion' => '',
    3091     );
    3092 
    3093     $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin );
    3094     if ( $plugin_data['Version'] ) {
    3095         $status['oldVersion'] = sprintf( __( 'Version %s' ), $plugin_data['Version'] );
    3096     }
    3097 
    3098     if ( ! current_user_can( 'update_plugins' ) ) {
    3099         $status['error'] = __( 'You do not have sufficient permissions to update plugins for this site.' );
    3100         wp_send_json_error( $status );
    3101     }
    3102 
    3103     check_ajax_referer( 'updates' );
    3104 
    3105     include_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
    3106 
    3107     wp_update_plugins();
    3108 
    3109     $skin = new Automatic_Upgrader_Skin();
    3110     $upgrader = new Plugin_Upgrader( $skin );
    3111     $result = $upgrader->bulk_upgrade( array( $plugin ) );
    3112 
    3113     if ( is_array( $result ) && empty( $result[$plugin] ) && is_wp_error( $skin->result ) ) {
    3114         $result = $skin->result;
    3115     }
    3116 
    3117     if ( is_array( $result ) && !empty( $result[ $plugin ] ) ) {
    3118         $plugin_update_data = current( $result );
    3119 
    3120         /*
    3121          * If the `update_plugins` site transient is empty (e.g. when you update
    3122          * two plugins in quick succession before the transient repopulates),
    3123          * this may be the return.
    3124          *
    3125          * Preferably something can be done to ensure `update_plugins` isn't empty.
    3126          * For now, surface some sort of error here.
    3127          */
    3128         if ( $plugin_update_data === true ) {
    3129             $status['error'] = __( 'Plugin update failed.' );
    3130             wp_send_json_error( $status );
    3131         }
    3132 
    3133         $plugin_data = get_plugins( '/' . $result[ $plugin ]['destination_name'] );
    3134         $plugin_data = reset( $plugin_data );
    3135 
    3136         if ( $plugin_data['Version'] ) {
    3137             $status['newVersion'] = sprintf( __( 'Version %s' ), $plugin_data['Version'] );
    3138         }
    3139 
    3140         wp_send_json_success( $status );
    3141     } else if ( is_wp_error( $result ) ) {
    3142         $status['error'] = $result->get_error_message();
    3143         wp_send_json_error( $status );
    3144 
    3145     } else if ( is_bool( $result ) && ! $result ) {
    3146         $status['errorCode'] = 'unable_to_connect_to_filesystem';
    3147         $status['error'] = __( 'Unable to connect to the filesystem. Please confirm your credentials.' );
    3148 
    3149         // Pass through the error from WP_Filesystem if one was raised
    3150         if ( is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->get_error_code() ) {
    3151             $status['error'] = $wp_filesystem->errors->get_error_message();
    3152         }
    3153 
    3154         wp_send_json_error( $status );
    3155 
    3156     } else {
    3157         // An unhandled error occured
    3158         $status['error'] = __( 'Plugin update failed.' );
    3159         wp_send_json_error( $status );
    3160     }
    31613092}
    31623093
     
    33343265    wp_send_json_success( update_user_meta( get_current_user_id(), 'wporg_favorites', $username ) );
    33353266}
     3267
     3268/**
     3269 * AJAX handler for installing a theme.
     3270 *
     3271 * @since 4.6.0
     3272 */
     3273function wp_ajax_install_theme() {
     3274    check_ajax_referer( 'updates' );
     3275
     3276    if ( empty( $_POST['slug'] ) ) {
     3277        wp_send_json_error( array(
     3278            'slug'         => '',
     3279            'errorCode'    => 'no_theme_specified',
     3280            'errorMessage' => __( 'No theme specified.' ),
     3281        ) );
     3282    }
     3283
     3284    $slug = sanitize_key( wp_unslash( $_POST['slug'] ) );
     3285
     3286    $status = array(
     3287        'install' => 'theme',
     3288        'slug'    => $slug,
     3289    );
     3290
     3291    if ( ! current_user_can( 'install_themes' ) ) {
     3292        $status['errorMessage'] = __( 'You do not have sufficient permissions to install themes on this site.' );
     3293        wp_send_json_error( $status );
     3294    }
     3295
     3296    include_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
     3297    include_once( ABSPATH . 'wp-admin/includes/theme.php' );
     3298
     3299    $api = themes_api( 'theme_information', array(
     3300        'slug'   => $slug,
     3301        'fields' => array( 'sections' => false ),
     3302    ) );
     3303
     3304    if ( is_wp_error( $api ) ) {
     3305        $status['errorMessage'] = $api->get_error_message();
     3306        wp_send_json_error( $status );
     3307    }
     3308
     3309    $upgrader = new Theme_Upgrader( new Automatic_Upgrader_Skin() );
     3310    $result   = $upgrader->install( $api->download_link );
     3311
     3312    if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
     3313        $status['debug'] = $upgrader->skin->get_upgrade_messages();
     3314    }
     3315
     3316    if ( is_wp_error( $result ) ) {
     3317        $status['errorMessage'] = $result->get_error_message();
     3318        wp_send_json_error( $status );
     3319    } elseif ( is_null( $result ) ) {
     3320        global $wp_filesystem;
     3321
     3322        $status['errorCode']    = 'unable_to_connect_to_filesystem';
     3323        $status['errorMessage'] = __( 'Unable to connect to the filesystem. Please confirm your credentials.' );
     3324
     3325        // Pass through the error from WP_Filesystem if one was raised.
     3326        if ( $wp_filesystem instanceof WP_Filesystem_Base && is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->get_error_code() ) {
     3327            $status['errorMessage'] = esc_html( $wp_filesystem->errors->get_error_message() );
     3328        }
     3329
     3330        wp_send_json_error( $status );
     3331    }
     3332
     3333    if ( current_user_can( 'switch_themes' ) ) {
     3334        if ( is_multisite() ) {
     3335            $status['activateUrl'] = add_query_arg( array(
     3336                'action'   => 'enable',
     3337                '_wpnonce' => wp_create_nonce( 'enable-theme_' . $slug ),
     3338                'theme'    => $slug,
     3339            ), network_admin_url( 'themes.php' ) );
     3340        } else {
     3341            $status['activateUrl'] = add_query_arg( array(
     3342                'action'     => 'activate',
     3343                '_wpnonce'   => wp_create_nonce( 'switch-theme_' . $slug ),
     3344                'stylesheet' => $slug,
     3345            ), admin_url( 'themes.php' ) );
     3346        }
     3347    }
     3348
     3349    if ( ! is_multisite() && current_user_can( 'edit_theme_options' ) && current_user_can( 'customize' ) ) {
     3350        $status['customizeUrl'] = add_query_arg( array(
     3351            'return' => urlencode( network_admin_url( 'theme-install.php', 'relative' ) ),
     3352        ), wp_customize_url( $slug ) );
     3353    }
     3354
     3355    /*
     3356     * See WP_Theme_Install_List_Table::_get_theme_status() if we wanted to check
     3357     * on post-install status.
     3358     */
     3359    wp_send_json_success( $status );
     3360}
     3361
     3362/**
     3363 * AJAX handler for updating a theme.
     3364 *
     3365 * @since 4.6.0
     3366 *
     3367 * @see Theme_Upgrader
     3368 */
     3369function wp_ajax_update_theme() {
     3370    check_ajax_referer( 'updates' );
     3371
     3372    if ( empty( $_POST['slug'] ) ) {
     3373        wp_send_json_error( array(
     3374            'slug'         => '',
     3375            'errorCode'    => 'no_theme_specified',
     3376            'errorMessage' => __( 'No theme specified.' ),
     3377        ) );
     3378    }
     3379
     3380    $stylesheet = sanitize_key( wp_unslash( $_POST['slug'] ) );
     3381    $status     = array(
     3382        'update'     => 'theme',
     3383        'slug'       => $stylesheet,
     3384        'newVersion' => '',
     3385    );
     3386
     3387    if ( ! current_user_can( 'update_themes' ) ) {
     3388        $status['errorMessage'] = __( 'You do not have sufficient permissions to update themes on this site.' );
     3389        wp_send_json_error( $status );
     3390    }
     3391
     3392    include_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
     3393
     3394    $current = get_site_transient( 'update_themes' );
     3395    if ( empty( $current ) ) {
     3396        wp_update_themes();
     3397    }
     3398
     3399    $upgrader = new Theme_Upgrader( new Automatic_Upgrader_Skin() );
     3400    $result   = $upgrader->bulk_upgrade( array( $stylesheet ) );
     3401
     3402    if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
     3403        $status['debug'] = $upgrader->skin->get_upgrade_messages();
     3404    }
     3405
     3406    if ( is_array( $result ) && ! empty( $result[ $stylesheet ] ) ) {
     3407
     3408        // Theme is already at the latest version.
     3409        if ( true === $result[ $stylesheet ] ) {
     3410            $status['errorMessage'] = $upgrader->strings['up_to_date'];
     3411            wp_send_json_error( $status );
     3412        }
     3413
     3414        $theme = wp_get_theme( $stylesheet );
     3415        if ( $theme->get( 'Version' ) ) {
     3416            $status['newVersion'] = $theme->get( 'Version' );
     3417        }
     3418
     3419        wp_send_json_success( $status );
     3420    } elseif ( is_wp_error( $upgrader->skin->result ) ) {
     3421        $status['errorCode']    = $upgrader->skin->result->get_error_code();
     3422        $status['errorMessage'] = $upgrader->skin->result->get_error_message();
     3423        wp_send_json_error( $status );
     3424    } elseif ( false === $result ) {
     3425        global $wp_filesystem;
     3426
     3427        $status['errorCode']    = 'unable_to_connect_to_filesystem';
     3428        $status['errorMessage'] = __( 'Unable to connect to the filesystem. Please confirm your credentials.' );
     3429
     3430        // Pass through the error from WP_Filesystem if one was raised.
     3431        if ( $wp_filesystem instanceof WP_Filesystem_Base && is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->get_error_code() ) {
     3432            $status['errorMessage'] = esc_html( $wp_filesystem->errors->get_error_message() );
     3433        }
     3434
     3435        wp_send_json_error( $status );
     3436    }
     3437
     3438    // An unhandled error occurred.
     3439    $status['errorMessage'] = __( 'Update failed.' );
     3440    wp_send_json_error( $status );
     3441}
     3442
     3443/**
     3444 * AJAX handler for deleting a theme.
     3445 *
     3446 * @since 4.6.0
     3447 */
     3448function wp_ajax_delete_theme() {
     3449    check_ajax_referer( 'updates' );
     3450
     3451    if ( empty( $_POST['slug'] ) ) {
     3452        wp_send_json_error( array(
     3453            'slug'         => '',
     3454            'errorCode'    => 'no_theme_specified',
     3455            'errorMessage' => __( 'No theme specified.' ),
     3456        ) );
     3457    }
     3458
     3459    $stylesheet = sanitize_key( wp_unslash( $_POST['slug'] ) );
     3460    $status     = array(
     3461        'delete' => 'theme',
     3462        'slug'   => $stylesheet,
     3463    );
     3464
     3465    if ( ! current_user_can( 'delete_themes' ) ) {
     3466        $status['errorMessage'] = __( 'You do not have sufficient permissions to delete themes on this site.' );
     3467        wp_send_json_error( $status );
     3468    }
     3469
     3470    if ( ! wp_get_theme( $stylesheet )->exists() ) {
     3471        $status['errorMessage'] = __( 'The requested theme does not exist.' );
     3472        wp_send_json_error( $status );
     3473    }
     3474
     3475    // Check filesystem credentials. `delete_plugins()` will bail otherwise.
     3476    ob_start();
     3477    $url = wp_nonce_url( 'themes.php?action=delete&stylesheet=' . urlencode( $stylesheet ), 'delete-theme_' . $stylesheet );
     3478    if ( false === ( $credentials = request_filesystem_credentials( $url ) ) || ! WP_Filesystem( $credentials ) ) {
     3479        global $wp_filesystem;
     3480        ob_end_clean();
     3481
     3482        $status['errorCode']    = 'unable_to_connect_to_filesystem';
     3483        $status['errorMessage'] = __( 'Unable to connect to the filesystem. Please confirm your credentials.' );
     3484
     3485        // Pass through the error from WP_Filesystem if one was raised.
     3486        if ( $wp_filesystem instanceof WP_Filesystem_Base && is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->get_error_code() ) {
     3487            $status['errorMessage'] = esc_html( $wp_filesystem->errors->get_error_message() );
     3488        }
     3489
     3490        wp_send_json_error( $status );
     3491    }
     3492
     3493    include_once( ABSPATH . 'wp-admin/includes/theme.php' );
     3494
     3495    $result = delete_theme( $stylesheet );
     3496
     3497    if ( is_wp_error( $result ) ) {
     3498        $status['errorMessage'] = $result->get_error_message();
     3499        wp_send_json_error( $status );
     3500    } elseif ( false === $result ) {
     3501        $status['errorMessage'] = __( 'Theme could not be deleted.' );
     3502        wp_send_json_error( $status );
     3503    }
     3504
     3505    wp_send_json_success( $status );
     3506}
     3507
     3508/**
     3509 * AJAX handler for installing a plugin.
     3510 *
     3511 * @since 4.6.0
     3512 */
     3513function wp_ajax_install_plugin() {
     3514    check_ajax_referer( 'updates' );
     3515
     3516    if ( empty( $_POST['slug'] ) ) {
     3517        wp_send_json_error( array(
     3518            'slug'         => '',
     3519            'errorCode'    => 'no_plugin_specified',
     3520            'errorMessage' => __( 'No plugin specified.' ),
     3521        ) );
     3522    }
     3523
     3524    $status = array(
     3525        'install' => 'plugin',
     3526        'slug'    => sanitize_key( wp_unslash( $_POST['slug'] ) ),
     3527    );
     3528
     3529    if ( ! current_user_can( 'install_plugins' ) ) {
     3530        $status['errorMessage'] = __( 'You do not have sufficient permissions to install plugins on this site.' );
     3531        wp_send_json_error( $status );
     3532    }
     3533
     3534    include_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
     3535    include_once( ABSPATH . 'wp-admin/includes/plugin-install.php' );
     3536
     3537    $api = plugins_api( 'plugin_information', array(
     3538        'slug'   => sanitize_key( wp_unslash( $_POST['slug'] ) ),
     3539        'fields' => array(
     3540            'sections' => false,
     3541        ),
     3542    ) );
     3543
     3544    if ( is_wp_error( $api ) ) {
     3545        $status['errorMessage'] = $api->get_error_message();
     3546        wp_send_json_error( $status );
     3547    }
     3548
     3549    $status['pluginName'] = $api->name;
     3550
     3551    $upgrader = new Plugin_Upgrader( new Automatic_Upgrader_Skin() );
     3552    $result   = $upgrader->install( $api->download_link );
     3553
     3554    if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
     3555        $status['debug'] = $upgrader->skin->get_upgrade_messages();
     3556    }
     3557
     3558    if ( is_wp_error( $result ) ) {
     3559        $status['errorMessage'] = $result->get_error_message();
     3560        wp_send_json_error( $status );
     3561    } elseif ( is_null( $result ) ) {
     3562        global $wp_filesystem;
     3563
     3564        $status['errorCode']    = 'unable_to_connect_to_filesystem';
     3565        $status['errorMessage'] = __( 'Unable to connect to the filesystem. Please confirm your credentials.' );
     3566
     3567        // Pass through the error from WP_Filesystem if one was raised.
     3568        if ( $wp_filesystem instanceof WP_Filesystem_Base && is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->get_error_code() ) {
     3569            $status['errorMessage'] = esc_html( $wp_filesystem->errors->get_error_message() );
     3570        }
     3571
     3572        wp_send_json_error( $status );
     3573    }
     3574
     3575    $install_status = install_plugin_install_status( $api );
     3576
     3577    if ( current_user_can( 'activate_plugins' ) && is_plugin_inactive( $install_status['file'] ) ) {
     3578        $status['activateUrl'] = add_query_arg( array(
     3579            '_wpnonce' => wp_create_nonce( 'activate-plugin_' . $install_status['file'] ),
     3580            'action'   => 'activate',
     3581            'plugin'   => $install_status['file'],
     3582        ), network_admin_url( 'plugins.php' ) );
     3583    }
     3584
     3585    if ( is_multisite() && current_user_can( 'manage_network_plugins' ) ) {
     3586        $status['activateUrl'] = add_query_arg( array( 'networkwide' => 1 ), $status['activateUrl'] );
     3587    }
     3588
     3589    wp_send_json_success( $status );
     3590}
     3591
     3592/**
     3593 * AJAX handler for updating a plugin.
     3594 *
     3595 * @since 4.2.0
     3596 *
     3597 * @see Plugin_Upgrader
     3598 */
     3599function wp_ajax_update_plugin() {
     3600    check_ajax_referer( 'updates' );
     3601
     3602    if ( empty( $_POST['plugin'] ) || empty( $_POST['slug'] ) ) {
     3603        wp_send_json_error( array(
     3604            'slug'         => '',
     3605            'errorCode'    => 'no_plugin_specified',
     3606            'errorMessage' => __( 'No plugin specified.' ),
     3607        ) );
     3608    }
     3609
     3610    $plugin      = plugin_basename( sanitize_text_field( wp_unslash( $_POST['plugin'] ) ) );
     3611    $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin );
     3612
     3613    $status = array(
     3614        'update'     => 'plugin',
     3615        'plugin'     => $plugin,
     3616        'slug'       => sanitize_key( wp_unslash( $_POST['slug'] ) ),
     3617        'pluginName' => $plugin_data['Name'],
     3618        'oldVersion' => '',
     3619        'newVersion' => '',
     3620    );
     3621
     3622    if ( $plugin_data['Version'] ) {
     3623        /* translators: %s: Plugin version */
     3624        $status['oldVersion'] = sprintf( __( 'Version %s' ), $plugin_data['Version'] );
     3625    }
     3626
     3627    if ( ! current_user_can( 'update_plugins' ) ) {
     3628        $status['errorMessage'] = __( 'You do not have sufficient permissions to update plugins for this site.' );
     3629        wp_send_json_error( $status );
     3630    }
     3631
     3632    include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
     3633
     3634    wp_update_plugins();
     3635
     3636    $skin     = new Automatic_Upgrader_Skin();
     3637    $upgrader = new Plugin_Upgrader( $skin );
     3638    $result   = $upgrader->bulk_upgrade( array( $plugin ) );
     3639
     3640    if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
     3641        $status['debug'] = $upgrader->skin->get_upgrade_messages();
     3642    }
     3643
     3644    if ( is_array( $result ) && empty( $result[ $plugin ] ) && is_wp_error( $skin->result ) ) {
     3645        $result = $skin->result;
     3646    }
     3647
     3648    if ( is_array( $result ) && ! empty( $result[ $plugin ] ) ) {
     3649        $plugin_update_data = current( $result );
     3650
     3651        /*
     3652         * If the `update_plugins` site transient is empty (e.g. when you update
     3653         * two plugins in quick succession before the transient repopulates),
     3654         * this may be the return.
     3655         *
     3656         * Preferably something can be done to ensure `update_plugins` isn't empty.
     3657         * For now, surface some sort of error here.
     3658         */
     3659        if ( true === $plugin_update_data ) {
     3660            $status['errorMessage'] = __( 'Plugin update failed.' );
     3661            wp_send_json_error( $status );
     3662        }
     3663
     3664        $plugin_data = get_plugins( '/' . $result[ $plugin ]['destination_name'] );
     3665        $plugin_data = reset( $plugin_data );
     3666
     3667        if ( $plugin_data['Version'] ) {
     3668            /* translators: %s: Plugin version */
     3669            $status['newVersion'] = sprintf( __( 'Version %s' ), $plugin_data['Version'] );
     3670        }
     3671        wp_send_json_success( $status );
     3672    } elseif ( is_wp_error( $result ) ) {
     3673        $status['errorMessage'] = $result->get_error_message();
     3674        wp_send_json_error( $status );
     3675    } elseif ( false === $result ) {
     3676        global $wp_filesystem;
     3677
     3678        $status['errorCode']    = 'unable_to_connect_to_filesystem';
     3679        $status['errorMessage'] = __( 'Unable to connect to the filesystem. Please confirm your credentials.' );
     3680
     3681        // Pass through the error from WP_Filesystem if one was raised.
     3682        if ( $wp_filesystem instanceof WP_Filesystem_Base && is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->get_error_code() ) {
     3683            $status['errorMessage'] = esc_html( $wp_filesystem->errors->get_error_message() );
     3684        }
     3685
     3686        wp_send_json_error( $status );
     3687    }
     3688
     3689    // An unhandled error occurred.
     3690    $status['errorMessage'] = __( 'Plugin update failed.' );
     3691    wp_send_json_error( $status );
     3692}
     3693
     3694/**
     3695 * AJAX handler for deleting a plugin.
     3696 *
     3697 * @since 4.6.0
     3698 */
     3699function wp_ajax_delete_plugin() {
     3700    check_ajax_referer( 'updates' );
     3701
     3702    if ( empty( $_POST['slug'] ) || empty( $_POST['plugin'] ) ) {
     3703        wp_send_json_error( array( 'errorCode' => 'no_plugin_specified' ) );
     3704    }
     3705
     3706    $plugin      = plugin_basename( sanitize_text_field( wp_unslash( $_POST['plugin'] ) ) );
     3707    $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin );
     3708
     3709    $status = array(
     3710        'delete'     => 'plugin',
     3711        'slug'       => sanitize_key( wp_unslash( $_POST['slug'] ) ),
     3712        'plugin'     => $plugin,
     3713        'pluginName' => $plugin_data['Name'],
     3714    );
     3715
     3716    if ( ! current_user_can( 'delete_plugins' ) ) {
     3717        $status['errorMessage'] = __( 'You do not have sufficient permissions to delete plugins for this site.' );
     3718        wp_send_json_error( $status );
     3719    }
     3720
     3721    if ( is_plugin_active( $plugin ) ) {
     3722        $status['errorMessage'] = __( 'You cannot delete a plugin while it is active on the main site.' );
     3723        wp_send_json_error( $status );
     3724    }
     3725
     3726    // Check filesystem credentials. `delete_plugins()` will bail otherwise.
     3727    ob_start();
     3728    $url = wp_nonce_url( 'plugins.php?action=delete-selected&verify-delete=1&checked[]=' . $plugin, 'bulk-plugins' );
     3729    if ( false === ( $credentials = request_filesystem_credentials( $url ) ) || ! WP_Filesystem( $credentials ) ) {
     3730        global $wp_filesystem;
     3731        ob_end_clean();
     3732
     3733        $status['errorCode']    = 'unable_to_connect_to_filesystem';
     3734        $status['errorMessage'] = __( 'Unable to connect to the filesystem. Please confirm your credentials.' );
     3735
     3736        // Pass through the error from WP_Filesystem if one was raised.
     3737        if ( $wp_filesystem instanceof WP_Filesystem_Base && is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->get_error_code() ) {
     3738            $status['errorMessage'] = esc_html( $wp_filesystem->errors->get_error_message() );
     3739        }
     3740
     3741        wp_send_json_error( $status );
     3742    }
     3743
     3744    $result = delete_plugins( array( $plugin ) );
     3745
     3746    if ( is_wp_error( $result ) ) {
     3747        $status['errorMessage'] = $result->get_error_message();
     3748        wp_send_json_error( $status );
     3749    } elseif ( false === $result ) {
     3750        $status['errorMessage'] = __( 'Plugin could not be deleted.' );
     3751        wp_send_json_error( $status );
     3752    }
     3753
     3754    wp_send_json_success( $status );
     3755}
     3756
     3757/**
     3758 * AJAX handler for searching plugins.
     3759 *
     3760 * @since 4.6.0
     3761 *
     3762 * @global WP_List_Table $wp_list_table Current list table instance.
     3763 * @global string        $hook_suffix   Current admin page.
     3764 * @global string        $s             Search term.
     3765 */
     3766function wp_ajax_search_plugins() {
     3767    check_ajax_referer( 'updates' );
     3768
     3769    global $wp_list_table, $hook_suffix, $s;
     3770    $hook_suffix = 'plugins.php';
     3771
     3772    /** @var WP_Plugins_List_Table $wp_list_table */
     3773    $wp_list_table = _get_list_table( 'WP_Plugins_List_Table' );
     3774    $status        = array();
     3775
     3776    if ( ! $wp_list_table->ajax_user_can() ) {
     3777        $status['errorMessage'] = __( 'You do not have sufficient permissions to manage plugins on this site.' );
     3778        wp_send_json_error( $status );
     3779    }
     3780
     3781    // Set the correct requester, so pagination works.
     3782    $_SERVER['REQUEST_URI'] = add_query_arg( array_diff_key( $_POST, array(
     3783        '_ajax_nonce' => null,
     3784        'action'      => null,
     3785    ) ), network_admin_url( 'plugins.php', 'relative' ) );
     3786
     3787    $s = sanitize_text_field( $_POST['s'] );
     3788
     3789    $wp_list_table->prepare_items();
     3790
     3791    ob_start();
     3792    $wp_list_table->display();
     3793    $status['items'] = ob_get_clean();
     3794
     3795    wp_send_json_success( $status );
     3796}
     3797
     3798/**
     3799 * AJAX handler for searching plugins to install.
     3800 *
     3801 * @since 4.6.0
     3802 *
     3803 * @global WP_List_Table $wp_list_table Current list table instance.
     3804 * @global string        $hook_suffix   Current admin page.
     3805 */
     3806function wp_ajax_search_install_plugins() {
     3807    check_ajax_referer( 'updates' );
     3808
     3809    global $wp_list_table, $hook_suffix;
     3810    $hook_suffix = 'plugin-install.php';
     3811
     3812    /** @var WP_Plugin_Install_List_Table $wp_list_table */
     3813    $wp_list_table = _get_list_table( 'WP_Plugin_Install_List_Table' );
     3814    $status        = array();
     3815
     3816    if ( ! $wp_list_table->ajax_user_can() ) {
     3817        $status['errorMessage'] = __( 'You do not have sufficient permissions to manage plugins on this site.' );
     3818        wp_send_json_error( $status );
     3819    }
     3820
     3821    // Set the correct requester, so pagination works.
     3822    $_SERVER['REQUEST_URI'] = add_query_arg( array_diff_key( $_POST, array(
     3823        '_ajax_nonce' => null,
     3824        'action'      => null,
     3825    ) ), network_admin_url( 'plugin-install.php', 'relative' ) );
     3826
     3827    $wp_list_table->prepare_items();
     3828
     3829    ob_start();
     3830    $wp_list_table->display();
     3831    $status['items'] = ob_get_clean();
     3832
     3833    wp_send_json_success( $status );
     3834}
Note: See TracChangeset for help on using the changeset viewer.