Upgrade/Install: Make some install/update failures more verbose.

An upgrader class is used in conjunction with an upgrader skin class. A skin class handles the logging for an upgrade and informs a user about the progress and failures.
The current Ajax install/update handlers are using the `Automatic_Upgrader_Skin` class because during an Ajax request no output is intended. The difference between Ajax updates and automatic updates is that you will see the full log (usually by email) while Ajax updates focus only on success or failure. For that `Automatic_Upgrader_Skin` has one disadvantage: It doesn't provide a way to retrieve failure messages which were passed through `WP_Upgrader_Skin::error()` by the upgrader.
To solve this issue a new skin `WP_Ajax_Upgrader_Skin` has been introduced. The skin extends `Automatic_Upgrader_Skin` and overrides the `error()` and `feedback()` methods to intercept all errors, which can be a `WP_Error` object or a string.

This updates all four Ajax handler for installing/updating themes/plugins to use the new skin. They now also check the skin for any intercepted errors and pass them on to the user.

Merge of [38199] to the 4.6 branch.

Props flixos90, obenland, ocean90.
Props DrewAPicture, pento for review.
See #37531.
Built from https://develop.svn.wordpress.org/branches/4.6@38200


git-svn-id: http://core.svn.wordpress.org/branches/4.6@38141 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
Dominik Schilling 2016-08-04 22:23:39 +00:00
parent 6ece312820
commit 9501efd09f
7 changed files with 186 additions and 25 deletions

View File

@ -3345,16 +3345,25 @@ function wp_ajax_install_theme() {
wp_send_json_error( $status );
}
$upgrader = new Theme_Upgrader( new Automatic_Upgrader_Skin() );
$skin = new WP_Ajax_Upgrader_Skin();
$upgrader = new Theme_Upgrader( $skin );
$result = $upgrader->install( $api->download_link );
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
$status['debug'] = $upgrader->skin->get_upgrade_messages();
$status['debug'] = $skin->get_upgrade_messages();
}
if ( is_wp_error( $result ) ) {
$status['errorCode'] = $result->get_error_code();
$status['errorMessage'] = $result->get_error_message();
wp_send_json_error( $status );
} elseif ( is_wp_error( $skin->result ) ) {
$status['errorCode'] = $skin->result->get_error_code();
$status['errorMessage'] = $skin->result->get_error_message();
wp_send_json_error( $status );
} elseif ( $skin->get_errors()->get_error_code() ) {
$status['errorMessage'] = $skin->get_error_messages();
wp_send_json_error( $status );
} elseif ( is_null( $result ) ) {
global $wp_filesystem;
@ -3437,14 +3446,22 @@ function wp_ajax_update_theme() {
wp_update_themes();
}
$upgrader = new Theme_Upgrader( new Automatic_Upgrader_Skin() );
$skin = new WP_Ajax_Upgrader_Skin();
$upgrader = new Theme_Upgrader( $skin );
$result = $upgrader->bulk_upgrade( array( $stylesheet ) );
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
$status['debug'] = $upgrader->skin->get_upgrade_messages();
$status['debug'] = $skin->get_upgrade_messages();
}
if ( is_array( $result ) && ! empty( $result[ $stylesheet ] ) ) {
if ( is_wp_error( $skin->result ) ) {
$status['errorCode'] = $skin->result->get_error_code();
$status['errorMessage'] = $skin->result->get_error_message();
wp_send_json_error( $status );
} elseif ( $skin->get_errors()->get_error_code() ) {
$status['errorMessage'] = $skin->get_error_messages();
wp_send_json_error( $status );
} elseif ( is_array( $result ) && ! empty( $result[ $stylesheet ] ) ) {
// Theme is already at the latest version.
if ( true === $result[ $stylesheet ] ) {
@ -3458,10 +3475,6 @@ function wp_ajax_update_theme() {
}
wp_send_json_success( $status );
} elseif ( is_wp_error( $upgrader->skin->result ) ) {
$status['errorCode'] = $upgrader->skin->result->get_error_code();
$status['errorMessage'] = $upgrader->skin->result->get_error_message();
wp_send_json_error( $status );
} elseif ( false === $result ) {
global $wp_filesystem;
@ -3594,16 +3607,25 @@ function wp_ajax_install_plugin() {
$status['pluginName'] = $api->name;
$upgrader = new Plugin_Upgrader( new Automatic_Upgrader_Skin() );
$skin = new WP_Ajax_Upgrader_Skin();
$upgrader = new Plugin_Upgrader( $skin );
$result = $upgrader->install( $api->download_link );
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
$status['debug'] = $upgrader->skin->get_upgrade_messages();
$status['debug'] = $skin->get_upgrade_messages();
}
if ( is_wp_error( $result ) ) {
$status['errorCode'] = $result->get_error_code();
$status['errorMessage'] = $result->get_error_message();
wp_send_json_error( $status );
} elseif ( is_wp_error( $skin->result ) ) {
$status['errorCode'] = $skin->result->get_error_code();
$status['errorMessage'] = $skin->result->get_error_message();
wp_send_json_error( $status );
} elseif ( $skin->get_errors()->get_error_code() ) {
$status['errorMessage'] = $skin->get_error_messages();
wp_send_json_error( $status );
} elseif ( is_null( $result ) ) {
global $wp_filesystem;
@ -3680,19 +3702,22 @@ function wp_ajax_update_plugin() {
wp_update_plugins();
$skin = new Automatic_Upgrader_Skin();
$skin = new WP_Ajax_Upgrader_Skin();
$upgrader = new Plugin_Upgrader( $skin );
$result = $upgrader->bulk_upgrade( array( $plugin ) );
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
$status['debug'] = $upgrader->skin->get_upgrade_messages();
$status['debug'] = $skin->get_upgrade_messages();
}
if ( is_array( $result ) && empty( $result[ $plugin ] ) && is_wp_error( $skin->result ) ) {
$result = $skin->result;
}
if ( is_array( $result ) && ! empty( $result[ $plugin ] ) ) {
if ( is_wp_error( $skin->result ) ) {
$status['errorCode'] = $skin->result->get_error_code();
$status['errorMessage'] = $skin->result->get_error_message();
wp_send_json_error( $status );
} elseif ( $skin->get_errors()->get_error_code() ) {
$status['errorMessage'] = $skin->get_error_messages();
wp_send_json_error( $status );
} elseif ( is_array( $result ) && ! empty( $result[ $plugin ] ) ) {
$plugin_update_data = current( $result );
/*
@ -3716,9 +3741,6 @@ function wp_ajax_update_plugin() {
$status['newVersion'] = sprintf( __( 'Version %s' ), $plugin_data['Version'] );
}
wp_send_json_success( $status );
} elseif ( is_wp_error( $result ) ) {
$status['errorMessage'] = $result->get_error_message();
wp_send_json_error( $status );
} elseif ( false === $result ) {
global $wp_filesystem;

View File

@ -0,0 +1,132 @@
<?php
/**
* Upgrader API: WP_Ajax_Upgrader_Skin class
*
* @package WordPress
* @subpackage Upgrader
* @since 4.6.0
*/
/**
* Upgrader Skin for Ajax WordPress upgrades.
*
* This skin is designed to be used for Ajax updates.
*
* @since 4.6.0
*
* @see Automatic_Upgrader_Skin
*/
class WP_Ajax_Upgrader_Skin extends Automatic_Upgrader_Skin {
/**
* Holds the WP_Error object.
*
* @since 4.6.0
* @access protected
* @var null|WP_Error
*/
protected $errors = null;
/**
* Constructor.
*
* @since 4.6.0
* @access public
*
* @param array $args Options for the upgrader, see WP_Upgrader_Skin::__construct().
*/
public function __construct( $args = array() ) {
parent::__construct( $args );
$this->errors = new WP_Error();
}
/**
* Retrieves the list of errors.
*
* @since 4.6.0
* @access public
*
* @return WP_Error Errors during an upgrade.
*/
public function get_errors() {
return $this->errors;
}
/**
* Retrieves a string for error messages.
*
* @since 4.6.0
* @access public
*
* @return string Error messages during an upgrade.
*/
public function get_error_messages() {
$messages = array();
foreach ( $this->errors->get_error_codes() as $error_code ) {
if ( $this->errors->get_error_data( $error_code ) && is_string( $this->errors->get_error_data( $error_code ) ) ) {
$messages[] = $this->errors->get_error_message( $error_code ) . ' ' . esc_html( strip_tags( $this->errors->get_error_data( $error_code ) ) );
} else {
$messages[] = $this->errors->get_error_message( $error_code );
}
}
return implode( ', ', $messages );
}
/**
* Stores a log entry for an error.
*
* @since 4.6.0
* @access public
*
* @param string|WP_Error $errors Errors.
*/
public function error( $errors ) {
if ( is_string( $errors ) ) {
$string = $errors;
if ( ! empty( $this->upgrader->strings[ $string ] ) ) {
$string = $this->upgrader->strings[ $string ];
}
if ( false !== strpos( $string, '%' ) ) {
$args = func_get_args();
$args = array_splice( $args, 1 );
if ( ! empty( $args ) ) {
$string = vsprintf( $string, $args );
}
}
// Count existing errors to generate an unique error code.
$errors_count = count( $errors->get_error_codes() );
$this->errors->add( 'unknown_upgrade_error_' . $errors_count + 1 , $string );
} elseif ( is_wp_error( $errors ) ) {
foreach ( $errors->get_error_codes() as $error_code ) {
$this->errors->add( $error_code, $errors->get_error_message( $error_code ), $errors->get_error_data( $error_code ) );
}
}
$args = func_get_args();
call_user_func_array( array( $this, 'parent::error' ), $args );
}
/**
* Stores a log entry.
*
* @since 4.6.0
* @access public
*
* @param string|array|WP_Error $data Log entry data.
*/
public function feedback( $data ) {
if ( is_wp_error( $data ) ) {
foreach ( $data->get_error_codes() as $error_code ) {
$this->errors->add( $error_code, $data->get_error_message( $error_code ), $data->get_error_data( $error_code ) );
}
}
$args = func_get_args();
call_user_func_array( array( $this, 'parent::feedback' ), $args );
}
}

View File

@ -36,3 +36,6 @@ require_once ABSPATH . 'wp-admin/includes/class-language-pack-upgrader-skin.php'
/** Automatic_Upgrader_Skin class */
require_once ABSPATH . 'wp-admin/includes/class-automatic-upgrader-skin.php';
/** WP_Ajax_Upgrader_Skin class */
require_once ABSPATH . 'wp-admin/includes/class-wp-ajax-upgrader-skin.php';

View File

@ -39,6 +39,9 @@ require_once ABSPATH . 'wp-admin/includes/class-language-pack-upgrader-skin.php'
/** Automatic_Upgrader_Skin class */
require_once ABSPATH . 'wp-admin/includes/class-automatic-upgrader-skin.php';
/** WP_Ajax_Upgrader_Skin class */
require_once ABSPATH . 'wp-admin/includes/class-wp-ajax-upgrader-skin.php';
/**
* Core class used for upgrading/installing a local set of files via
* the Filesystem Abstraction classes from a Zip file.

View File

@ -244,7 +244,7 @@
* @param {string=} response.errorCode Optional. Error code for an error that occurred.
*/
wp.updates.ajaxAlways = function( response ) {
if ( ! response.errorCode && 'unable_to_connect_to_filesystem' !== response.errorCode ) {
if ( ! response.errorCode || 'unable_to_connect_to_filesystem' !== response.errorCode ) {
wp.updates.ajaxLocked = false;
wp.updates.queueChecker();
}
@ -1533,7 +1533,7 @@
* @returns {boolean} Whether there is an error that needs to be handled or not.
*/
wp.updates.maybeHandleCredentialError = function( response, action ) {
if ( response.errorCode && 'unable_to_connect_to_filesystem' === response.errorCode ) {
if ( wp.updates.shouldRequestFilesystemCredentials && response.errorCode && 'unable_to_connect_to_filesystem' === response.errorCode ) {
wp.updates.credentialError( response, action );
return true;
}

File diff suppressed because one or more lines are too long

View File

@ -4,7 +4,7 @@
*
* @global string $wp_version
*/
$wp_version = '4.6-RC1-38197';
$wp_version = '4.6-RC1-38200';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.