diff --git a/includes/abstracts/abstract-wc-data.php b/includes/abstracts/abstract-wc-data.php index dfc436bd392..c2b83cde41e 100644 --- a/includes/abstracts/abstract-wc-data.php +++ b/includes/abstracts/abstract-wc-data.php @@ -539,11 +539,14 @@ abstract class WC_Data { /** * When invalid data is found, throw an exception unless reading from the DB. - * @param string $error_code Error code. - * @param string $error_message Error message. + * * @throws WC_Data_Exception + * @param string $code Error code. + * @param string $message Error message. + * @param int $http_status_code HTTP status code. + * @param array $data Extra error data. */ - protected function error( $error_code, $error_message ) { - throw new WC_Data_Exception( $error_code, $error_message ); + protected function error( $code, $message, $http_status_code = 400, $data = array() ) { + throw new WC_Data_Exception( $code, $message, $http_status_code, $data ); } } diff --git a/includes/abstracts/abstract-wc-product.php b/includes/abstracts/abstract-wc-product.php index 64264cfae5c..133e5bed008 100644 --- a/includes/abstracts/abstract-wc-product.php +++ b/includes/abstracts/abstract-wc-product.php @@ -804,7 +804,9 @@ class WC_Product extends WC_Abstract_Legacy_Product { public function set_sku( $sku ) { $sku = (string) $sku; if ( $this->get_object_read() && ! empty( $sku ) && ! wc_product_has_unique_sku( $this->get_id(), $sku ) ) { - $this->error( 'product_invalid_sku', __( 'Invalid or duplicated SKU.', 'woocommerce' ) ); + $sku_found = wc_get_product_id_by_sku( $sku ); + + $this->error( 'product_invalid_sku', __( 'Invalid or duplicated SKU.', 'woocommerce' ), 400, array( 'resource_id' => $sku_found ) ); } $this->set_prop( 'sku', $sku ); } diff --git a/includes/abstracts/abstract-wc-rest-terms-controller.php b/includes/abstracts/abstract-wc-rest-terms-controller.php index 6eaa570f112..a53e2161788 100644 --- a/includes/abstracts/abstract-wc-rest-terms-controller.php +++ b/includes/abstracts/abstract-wc-rest-terms-controller.php @@ -378,15 +378,15 @@ abstract class WC_REST_Terms_Controller extends WC_REST_Controller { $term = wp_insert_term( $name, $taxonomy, $args ); if ( is_wp_error( $term ) ) { + $error_data = array( 'status' => 400 ); - // If we're going to inform the client that the term exists, give them the identifier - // they can actually use. - if ( ( $term_id = $term->get_error_data( 'term_exists' ) ) ) { - $existing_term = get_term( $term_id, $taxonomy ); - $term->add_data( $existing_term->term_id, 'term_exists' ); + // If we're going to inform the client that the term exists, + // give them the identifier they can actually use. + if ( $term_id = $term->get_error_data( 'term_exists' ) ) { + $error_data['resource_id'] = $term_id; } - return $term; + return new WP_Error( $term->get_error_code(), $term->get_error_message(), $error_data ); } $term = get_term( $term['term_id'], $taxonomy ); diff --git a/includes/api/class-wc-rest-coupons-controller.php b/includes/api/class-wc-rest-coupons-controller.php index 4b151ea243e..160161106ec 100644 --- a/includes/api/class-wc-rest-coupons-controller.php +++ b/includes/api/class-wc-rest-coupons-controller.php @@ -364,7 +364,7 @@ class WC_REST_Coupons_Controller extends WC_REST_Posts_Controller { $coupon->save(); return $coupon->get_id(); } catch ( WC_Data_Exception $e ) { - return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); + return new WP_Error( $e->getErrorCode(), $e->getMessage(), $e->getErrorData() ); } catch ( WC_REST_Exception $e ) { return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); } diff --git a/includes/api/class-wc-rest-orders-controller.php b/includes/api/class-wc-rest-orders-controller.php index 7f8e4b5989e..d96e79c595b 100644 --- a/includes/api/class-wc-rest-orders-controller.php +++ b/includes/api/class-wc-rest-orders-controller.php @@ -437,7 +437,7 @@ class WC_REST_Orders_Controller extends WC_REST_Posts_Controller { return $order->get_id(); } catch ( WC_Data_Exception $e ) { - return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); + return new WP_Error( $e->getErrorCode(), $e->getMessage(), $e->getErrorData() ); } catch ( WC_REST_Exception $e ) { return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); } @@ -466,7 +466,7 @@ class WC_REST_Orders_Controller extends WC_REST_Posts_Controller { return $order->get_id(); } catch ( WC_Data_Exception $e ) { - return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); + return new WP_Error( $e->getErrorCode(), $e->getMessage(), $e->getErrorData() ); } catch ( WC_REST_Exception $e ) { return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); } diff --git a/includes/api/class-wc-rest-products-controller.php b/includes/api/class-wc-rest-products-controller.php index b8a5ec4b6e1..4b363519f8e 100644 --- a/includes/api/class-wc-rest-products-controller.php +++ b/includes/api/class-wc-rest-products-controller.php @@ -766,7 +766,7 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller { return $response; } catch ( WC_Data_Exception $e ) { $this->delete_post( $product_id ); - return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); + return new WP_Error( $e->getErrorCode(), $e->getMessage(), $e->getErrorData() ); } catch ( WC_REST_Exception $e ) { $this->delete_post( $product_id ); return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); @@ -805,7 +805,7 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller { return rest_ensure_response( $response ); } catch ( WC_Data_Exception $e ) { - return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); + return new WP_Error( $e->getErrorCode(), $e->getMessage(), $e->getErrorData() ); } catch ( WC_REST_Exception $e ) { return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); } diff --git a/includes/class-wc-data-exception.php b/includes/class-wc-data-exception.php index 37d2220d363..67a3d8cb696 100644 --- a/includes/class-wc-data-exception.php +++ b/includes/class-wc-data-exception.php @@ -4,10 +4,10 @@ * * Extends Exception to provide additional data. * - * @author WooThemes - * @category Core - * @package WooCommerce - * @since 2.7 + * @author WooThemes + * @category Core + * @package WooCommerce + * @since 2.7 */ if ( ! defined( 'ABSPATH' ) ) { @@ -15,34 +15,54 @@ if ( ! defined( 'ABSPATH' ) ) { } /** - * WC_Data_Exception class + * WC_Data_Exception class. */ class WC_Data_Exception extends Exception { - /** @var string sanitized error code */ + /** + * Sanitized error code. + * + * @var string + */ protected $error_code; + /** + * Error extra data. + * + * @var array + */ + protected $error_data; + /** * Setup exception. * - * error code - machine-readable, e.g. `woocommerce_invalid_product_id` - * error message - friendly message, e.g. 'Product ID is invalid' - * http status code - proper HTTP status code to respond with, e.g. 400 - * - * @param string $error_code - * @param string $error_message user-friendly translated error message - * @param int $http_status_code HTTP status code to respond with + * @param string $code Machine-readable error code, e.g `woocommerce_invalid_product_id`. + * @param string $message User-friendly translated error message, e.g. 'Product ID is invalid'. + * @param int $http_status_code Proper HTTP status code to respond with, e.g. 400. + * @param array $data Extra error data. */ - public function __construct( $error_code, $error_message, $http_status_code = 400 ) { - $this->error_code = $error_code; - parent::__construct( $error_message, $http_status_code ); + public function __construct( $code, $message, $http_status_code = 400, $data = array() ) { + $this->error_code = $code; + $this->error_data = array_merge( array( 'status' => $http_status_code ), $data ); + + parent::__construct( $message, $http_status_code ); } /** - * Returns the error code + * Returns the error code. + * * @return string */ public function getErrorCode() { return $this->error_code; } + + /** + * Returns error data. + * + * @return array + */ + public function getErrorData() { + return $this->error_data; + } }