From 938361535f1083fa35f7c95b89fd80c83d3ea3e3 Mon Sep 17 00:00:00 2001 From: Mike Jolley Date: Wed, 24 Aug 2016 16:02:19 +0100 Subject: [PATCH] Exception handling --- .../abstracts/abstract-wc-legacy-order.php | 9 ++ includes/abstracts/abstract-wc-order.php | 1 + includes/admin/wc-admin-functions.php | 63 ++++++++----- includes/class-wc-ajax.php | 88 ++++++++++--------- includes/class-wc-order-item-product.php | 2 +- includes/class-wc-order.php | 73 ++++++++------- includes/wc-core-functions.php | 9 +- includes/wc-order-functions.php | 4 +- 8 files changed, 145 insertions(+), 104 deletions(-) diff --git a/includes/abstracts/abstract-wc-legacy-order.php b/includes/abstracts/abstract-wc-legacy-order.php index b517762bfcb..ae103c5142c 100644 --- a/includes/abstracts/abstract-wc-legacy-order.php +++ b/includes/abstracts/abstract-wc-legacy-order.php @@ -22,6 +22,7 @@ abstract class WC_Abstract_Legacy_Order extends WC_Data { * @param int $discount tax amount. * @param int $discount_tax amount. * @return int order item ID + * @throws WC_Data_Exception */ public function add_coupon( $code = array(), $discount = 0, $discount_tax = 0 ) { _deprecated_function( 'WC_Order::add_coupon', '2.7', 'Create new WC_Order_Item_Coupon object and add to order with WC_Order::add_item()' ); @@ -44,6 +45,7 @@ abstract class WC_Abstract_Legacy_Order extends WC_Data { * @param int $tax_amount amount of tax. * @param int $shipping_tax_amount shipping amount. * @return int order item ID + * @throws WC_Data_Exception */ public function add_tax( $tax_rate_id, $tax_amount = 0, $shipping_tax_amount = 0 ) { _deprecated_function( 'WC_Order::add_tax', '2.7', 'Create new WC_Order_Item_Tax object and add to order with WC_Order::add_item()' ); @@ -65,6 +67,7 @@ abstract class WC_Abstract_Legacy_Order extends WC_Data { * Add a shipping row to the order. * @param WC_Shipping_Rate shipping_rate * @return int order item ID + * @throws WC_Data_Exception */ public function add_shipping( $shipping_rate ) { _deprecated_function( 'WC_Order::add_shipping', '2.7', 'Create new WC_Order_Item_Shipping object and add to order with WC_Order::add_item()' ); @@ -88,6 +91,7 @@ abstract class WC_Abstract_Legacy_Order extends WC_Data { * Order must be saved prior to adding items. * @param object $fee * @return int updated order item ID + * @throws WC_Data_Exception */ public function add_fee( $fee ) { _deprecated_function( 'WC_Order::add_fee', '2.7', 'Create new WC_Order_Item_Fee object and add to order with WC_Order::add_item()' ); @@ -117,6 +121,7 @@ abstract class WC_Abstract_Legacy_Order extends WC_Data { * @param WC_Product $product * @param array $args data to update. * @return int updated order item ID + * @throws WC_Data_Exception */ public function update_product( $item, $product, $args ) { _deprecated_function( 'WC_Order::update_product', '2.7', 'Interact with WC_Order_Item_Product class' ); @@ -165,6 +170,7 @@ abstract class WC_Abstract_Legacy_Order extends WC_Data { * @param object|int $item * @param array $args * @return int updated order item ID + * @throws WC_Data_Exception */ public function update_coupon( $item, $args ) { _deprecated_function( 'WC_Order::update_coupon', '2.7', 'Interact with WC_Order_Item_Coupon class' ); @@ -203,6 +209,7 @@ abstract class WC_Abstract_Legacy_Order extends WC_Data { * @param object|int $item * @param array $args * @return int updated order item ID + * @throws WC_Data_Exception */ public function update_shipping( $item, $args ) { _deprecated_function( 'WC_Order::update_shipping', '2.7', 'Interact with WC_Order_Item_Shipping class' ); @@ -239,6 +246,7 @@ abstract class WC_Abstract_Legacy_Order extends WC_Data { * @param object|int $item * @param array $args * @return int updated order item ID + * @throws WC_Data_Exception */ public function update_fee( $item, $args ) { _deprecated_function( 'WC_Order::update_fee', '2.7', 'Interact with WC_Order_Item_Fee class' ); @@ -269,6 +277,7 @@ abstract class WC_Abstract_Legacy_Order extends WC_Data { * @param object|int $item * @param array $args * @return int updated order item ID + * @throws WC_Data_Exception */ public function update_tax( $item, $args ) { _deprecated_function( 'WC_Order::update_tax', '2.7', 'Interact with WC_Order_Item_Tax class' ); diff --git a/includes/abstracts/abstract-wc-order.php b/includes/abstracts/abstract-wc-order.php index 92e7be3ba01..45c943bdff7 100644 --- a/includes/abstracts/abstract-wc-order.php +++ b/includes/abstracts/abstract-wc-order.php @@ -998,6 +998,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order { * @param int $qty * @param array $args * @return int order item ID + * @throws WC_Data_Exception */ public function add_product( $product, $qty = 1, $args = array() ) { if ( $product ) { diff --git a/includes/admin/wc-admin-functions.php b/includes/admin/wc-admin-functions.php index 258f46c465d..2bbe3aebffc 100644 --- a/includes/admin/wc-admin-functions.php +++ b/includes/admin/wc-admin-functions.php @@ -190,16 +190,28 @@ function wc_save_order_items( $order_id, $items ) { continue; } - if ( isset( $items['order_item_name'][ $item_id ] ) ) { - $item->set_name( wc_clean( wp_unslash( $items['order_item_name'][ $item_id ] ) ) ); - } + $line_tax = isset( $items['line_tax'][ $item_id ] ) ? $items['line_tax'][ $item_id ] : array(); + $line_subtotal_tax = isset( $items['line_subtotal_tax'][ $item_id ] ) ? $items['line_subtotal_tax'][ $item_id ]: $line_tax; + $set_data = array( + 'name' => isset( $items['order_item_name'][ $item_id ] ) ? $items['order_item_name'][ $item_id ] : null, + 'quantity' => isset( $items['order_item_qty'][ $item_id ] ) ? $items['order_item_qty'][ $item_id ] : null, + 'tax_class' => isset( $items['order_item_tax_class'][ $item_id ] ) ? $items['order_item_tax_class'][ $item_id ] : null, + 'total' => isset( $items['line_total'][ $item_id ] ) ? $items['line_total'][ $item_id ] : 0, + 'total_tax' => array_sum( $line_tax ), + 'subtotal' => isset( $items['line_subtotal'][ $item_id ] ) ? $items['line_subtotal'][ $item_id ] : $item->get_total(), + 'subtotal_tax' => array_sum( $line_subtotal_tax ), + 'taxes' => array( 'total' => $line_tax, 'subtotal' => $line_subtotal_tax ), + ); - if ( isset( $items['order_item_qty'][ $item_id ] ) && is_callable( array( $item, 'set_quantity' ) ) ) { - $item->set_quantity( $items['order_item_qty'][ $item_id ] ); - } - - if ( isset( $items['order_item_tax_class'][ $item_id ] ) ) { - $item->set_tax_class( wc_clean( $items['order_item_tax_class'][ $item_id ] ) ); + foreach ( $set_data as $prop => $value ) { + try { + $setter = "set_$prop"; + if ( ! is_null( $value ) && is_callable( array( $item, $setter ) ) ) { + $item->{$setter}( wc_clean( wp_unslash( $value ) ) ); + } + } catch ( WC_Data_Exception $e ) { + unset( $e ); // Skip prop and leave set to default + } } if ( isset( $items['meta_key'][ $item_id ], $items['meta_value'][ $item_id ] ) ) { @@ -219,17 +231,6 @@ function wc_save_order_items( $order_id, $items ) { } } - $line_tax = isset( $items['line_tax'][ $item_id ] ) ? $items['line_tax'][ $item_id ]: array(); - $line_subtotal_tax = isset( $items['line_subtotal_tax'][ $item_id ] ) ? $items['line_subtotal_tax'][ $item_id ]: $line_tax; - $item->set_total( isset( $items['line_total'][ $item_id ] ) ? $items['line_total'][ $item_id ] : 0 ); - $item->set_total_tax( array_sum( $line_tax ) ); - - if ( is_callable( array( $item, 'set_subtotal' ) ) ) { - $item->set_subtotal( isset( $items['line_subtotal'][ $item_id ] ) ? $items['line_subtotal'][ $item_id ] : $item->get_total() ); - $item->set_subtotal_tax( array_sum( $line_subtotal_tax ) ); - } - - $item->set_taxes( array( 'total' => $line_tax, 'subtotal' => $line_subtotal_tax ) ); $item->save(); } } @@ -240,10 +241,24 @@ function wc_save_order_items( $order_id, $items ) { if ( ! $item = $order->get_item( absint( $item_id ) ) ) { continue; } - $item->set_method_id( isset( $items['shipping_method'][ $item_id ] ) ? wc_clean( $items['shipping_method'][ $item_id ] ) : '' ); - $item->set_method_title( isset( $items['shipping_method_title'][ $item_id ] ) ? wc_clean( wp_unslash( $items['shipping_method_title'][ $item_id ] ) ) : '' ); - $item->set_total( isset( $items['shipping_cost'][ $item_id ] ) ? $items['shipping_cost'][ $item_id ] : '' ); - $item->set_taxes( array( 'total' => isset( $items['shipping_taxes'][ $item_id ] ) ? $items['shipping_taxes'][ $item_id ] : array() ) ); + + $set_data = array( + 'method_id' => isset( $items['shipping_method'][ $item_id ] ) ? $items['shipping_method'][ $item_id ] : null, + 'method_title' => isset( $items['shipping_method_title'][ $item_id ] ) ? $items['shipping_method_title'][ $item_id ] : null, + 'total' => isset( $items['shipping_cost'][ $item_id ] ) ? $items['shipping_cost'][ $item_id ] : 0, + 'taxes' => array( 'total' => isset( $items['shipping_taxes'][ $item_id ] ) ? $items['shipping_taxes'][ $item_id ] : array() ), + ); + + foreach ( $set_data as $prop => $value ) { + try { + $setter = "set_$prop"; + if ( is_callable( array( $item, $setter ) ) ) { + $item->{$setter}( wc_clean( wp_unslash( $value ) ) ); + } + } catch ( WC_Data_Exception $e ) { + unset( $e ); // Skip prop and leave set to default + } + } if ( isset( $items['meta_key'][ $item_id ], $items['meta_value'][ $item_id ] ) ) { foreach ( $items['meta_key'][ $item_id ] as $meta_id => $meta_key ) { diff --git a/includes/class-wc-ajax.php b/includes/class-wc-ajax.php index 9b07648570f..f0704a40058 100644 --- a/includes/class-wc-ajax.php +++ b/includes/class-wc-ajax.php @@ -1134,28 +1134,30 @@ class WC_AJAX { die(-1); } - $item_to_add = sanitize_text_field( $_POST['item_to_add'] ); - $order_id = absint( $_POST['order_id'] ); + try { + $item_to_add = sanitize_text_field( $_POST['item_to_add'] ); + $order_id = absint( $_POST['order_id'] ); - // Find the item - if ( ! is_numeric( $item_to_add ) ) { - die(); - } + // Find the item + if ( ! is_numeric( $item_to_add ) ) { + die(); + } - $post = get_post( $item_to_add ); + $post = get_post( $item_to_add ); - if ( ! $post || ( 'product' !== $post->post_type && 'product_variation' !== $post->post_type ) ) { - die(); - } + if ( ! $post || ( 'product' !== $post->post_type && 'product_variation' !== $post->post_type ) ) { + die(); + } - $product = wc_get_product( $post->ID ); - $order = wc_get_order( $order_id ); - $order_taxes = $order->get_taxes(); - $class = 'new_row'; - $item_id = $order->add_product( $product ); - $item = apply_filters( 'woocommerce_ajax_order_item', $order->get_item( $item_id ), $item_id ); + $product = wc_get_product( $post->ID ); + $order = wc_get_order( $order_id ); + $order_taxes = $order->get_taxes(); + $class = 'new_row'; + $item_id = $order->add_product( $product ); + $item = apply_filters( 'woocommerce_ajax_order_item', $order->get_item( $item_id ), $item_id ); - do_action( 'woocommerce_ajax_add_order_item_meta', $item_id, $item ); + do_action( 'woocommerce_ajax_add_order_item_meta', $item_id, $item ); + } catch ( Exception $e ) {} include( 'admin/meta-boxes/views/html-order-item.php' ); die(); @@ -1172,12 +1174,14 @@ class WC_AJAX { die(-1); } - $order_id = absint( $_POST['order_id'] ); - $order = wc_get_order( $order_id ); - $order_taxes = $order->get_taxes(); - $item = new WC_Order_Item_Fee(); - $item->set_order_id( $order_id ); - $item_id = $item->save(); + try { + $order_id = absint( $_POST['order_id'] ); + $order = wc_get_order( $order_id ); + $order_taxes = $order->get_taxes(); + $item = new WC_Order_Item_Fee(); + $item->set_order_id( $order_id ); + $item_id = $item->save(); + } catch ( Exception $e ) {} include( 'admin/meta-boxes/views/html-order-fee.php' ); @@ -1196,15 +1200,17 @@ class WC_AJAX { die(-1); } - $order_id = absint( $_POST['order_id'] ); - $order = wc_get_order( $order_id ); - $order_taxes = $order->get_taxes(); - $shipping_methods = WC()->shipping() ? WC()->shipping->load_shipping_methods() : array(); + try { + $order_id = absint( $_POST['order_id'] ); + $order = wc_get_order( $order_id ); + $order_taxes = $order->get_taxes(); + $shipping_methods = WC()->shipping() ? WC()->shipping->load_shipping_methods() : array(); - // Add new shipping - $item = new WC_Order_Item_Shipping(); - $item->set_shipping_rate( new WC_Shipping_Rate() ); - $order->add_item( $item ); + // Add new shipping + $item = new WC_Order_Item_Shipping(); + $item->set_shipping_rate( new WC_Shipping_Rate() ); + $order->add_item( $item ); + } catch ( Exception $e ) {} include( 'admin/meta-boxes/views/html-order-shipping.php' ); @@ -1224,16 +1230,18 @@ class WC_AJAX { die(-1); } - $order_id = absint( $_POST['order_id'] ); - $rate_id = absint( $_POST['rate_id'] ); - $order = wc_get_order( $order_id ); - $data = get_post_meta( $order_id ); + try { + $order_id = absint( $_POST['order_id'] ); + $rate_id = absint( $_POST['rate_id'] ); + $order = wc_get_order( $order_id ); + $data = get_post_meta( $order_id ); - // Add new tax - $item = new WC_Order_Item_Tax(); - $item->set_rate( $rate_id ); - $item->set_order_id( $order_id ); - $item->save(); + // Add new tax + $item = new WC_Order_Item_Tax(); + $item->set_rate( $rate_id ); + $item->set_order_id( $order_id ); + $item->save(); + } catch ( Exception $e ) {} // Return HTML items include( 'admin/meta-boxes/views/html-order-items.php' ); diff --git a/includes/class-wc-order-item-product.php b/includes/class-wc-order-item-product.php index 984416eebc1..07a987d26ab 100644 --- a/includes/class-wc-order-item-product.php +++ b/includes/class-wc-order-item-product.php @@ -24,7 +24,7 @@ class WC_Order_Item_Product extends WC_Order_Item { 'name' => '', 'product_id' => 0, 'variation_id' => 0, - 'quantity' => 0, + 'quantity' => 1, 'tax_class' => '', 'subtotal' => 0, 'subtotal_tax' => 0, diff --git a/includes/class-wc-order.php b/includes/class-wc-order.php index 6d25d66b77c..e7a7cfce07a 100644 --- a/includes/class-wc-order.php +++ b/includes/class-wc-order.php @@ -118,45 +118,47 @@ class WC_Order extends WC_Abstract_Order { * @return bool success */ public function payment_complete( $transaction_id = '' ) { - if ( ! $this->get_id() ) { - return false; - } + try { + if ( ! $this->get_id() ) { + throw new Exception( 'Missing ID' ); + } + do_action( 'woocommerce_pre_payment_complete', $this->get_id() ); - do_action( 'woocommerce_pre_payment_complete', $this->get_id() ); + if ( ! empty( WC()->session ) ) { + WC()->session->set( 'order_awaiting_payment', false ); + } - if ( ! empty( WC()->session ) ) { - WC()->session->set( 'order_awaiting_payment', false ); - } + if ( $this->has_status( apply_filters( 'woocommerce_valid_order_statuses_for_payment_complete', array( 'on-hold', 'pending', 'failed', 'cancelled' ), $this ) ) ) { + $order_needs_processing = false; - if ( $this->has_status( apply_filters( 'woocommerce_valid_order_statuses_for_payment_complete', array( 'on-hold', 'pending', 'failed', 'cancelled' ), $this ) ) ) { - $order_needs_processing = false; + if ( sizeof( $this->get_items() ) > 0 ) { + foreach ( $this->get_items() as $item ) { + if ( $item->is_type( 'line_item' ) && ( $product = $item->get_product() ) ) { + $virtual_downloadable_item = $product->is_downloadable() && $product->is_virtual(); - if ( sizeof( $this->get_items() ) > 0 ) { - foreach ( $this->get_items() as $item ) { - if ( $item->is_type( 'line_item' ) && ( $product = $item->get_product() ) ) { - $virtual_downloadable_item = $product->is_downloadable() && $product->is_virtual(); - - if ( apply_filters( 'woocommerce_order_item_needs_processing', ! $virtual_downloadable_item, $product, $this->get_id() ) ) { - $order_needs_processing = true; - break; + if ( apply_filters( 'woocommerce_order_item_needs_processing', ! $virtual_downloadable_item, $product, $this->get_id() ) ) { + $order_needs_processing = true; + break; + } } } } + + if ( ! empty( $transaction_id ) ) { + $this->set_transaction_id( $transaction_id ); + } + + $this->set_status( apply_filters( 'woocommerce_payment_complete_order_status', $order_needs_processing ? 'processing' : 'completed', $this->get_id() ) ); + $this->set_date_paid( current_time( 'timestamp' ) ); + $this->save(); + + do_action( 'woocommerce_payment_complete', $this->get_id() ); + } else { + do_action( 'woocommerce_payment_complete_order_status_' . $this->get_status(), $this->get_id() ); } - - if ( ! empty( $transaction_id ) ) { - $this->set_transaction_id( $transaction_id ); - } - - $this->set_status( apply_filters( 'woocommerce_payment_complete_order_status', $order_needs_processing ? 'processing' : 'completed', $this->get_id() ) ); - $this->set_date_paid( current_time( 'timestamp' ) ); - $this->save(); - - do_action( 'woocommerce_payment_complete', $this->get_id() ); - } else { - do_action( 'woocommerce_payment_complete_order_status_' . $this->get_status(), $this->get_id() ); + } catch ( Exception $e ) { + return false; } - return true; } @@ -412,13 +414,18 @@ class WC_Order extends WC_Abstract_Order { /** * Updates status of order immediately. Order must exist. * @uses WC_Order::set_status() + * @return bool success */ public function update_status( $new_status, $note = '', $manual = false ) { - if ( ! $this->get_id() ) { + try { + if ( ! $this->get_id() ) { + throw new Exception( 'Missing ID' ); + } + $this->set_status( $new_status, $note, $manual ); + $this->save(); + } catch ( Exception $e ) { return false; } - $this->set_status( $new_status, $note, $manual ); - $this->save(); return true; } diff --git a/includes/wc-core-functions.php b/includes/wc-core-functions.php index 77eca21a4a2..3eae0d9c15e 100644 --- a/includes/wc-core-functions.php +++ b/includes/wc-core-functions.php @@ -54,7 +54,7 @@ add_filter( 'woocommerce_short_description', 'do_shortcode', 11 ); // AFTER wpau * Returns a new order object on success which can then be used to add additional data. * * @param array $args - * @return WC_Order + * @return WC_Order|WP_Error */ function wc_create_order( $args = array() ) { $default_args = array( @@ -67,8 +67,8 @@ function wc_create_order( $args = array() ) { 'order_id' => 0, ); - $args = wp_parse_args( $args, $default_args ); try { + $args = wp_parse_args( $args, $default_args ); $order = new WC_Order( $args['order_id'] ); // Update props that were set (not null) @@ -102,9 +102,10 @@ function wc_create_order( $args = array() ) { $order->set_customer_ip_address( WC_Geolocation::get_ip_address() ); $order->set_customer_user_agent( wc_get_user_agent() ); $order->save(); - } catch( WC_Data_Exception $e ) { - + } catch ( Exception $e ) { + return new WP_Error( 'error', $e->getMessage() ); } + return $order; } diff --git a/includes/wc-order-functions.php b/includes/wc-order-functions.php index 2fddfffdb35..3a199c25656 100644 --- a/includes/wc-order-functions.php +++ b/includes/wc-order-functions.php @@ -819,7 +819,7 @@ function wc_create_refund( $args = array() ) { $refund = new WC_Order_Refund( $args['refund_id'] ); if ( ! $order ) { - return new WP_Error( 'error', __( 'Invalid order ID.', 'woocommerce' ) ); + throw new Exception( __( 'Invalid order ID.', 'woocommerce' ) ); } // prevent negative refunds @@ -871,7 +871,7 @@ function wc_create_refund( $args = array() ) { $refund->save(); } catch ( Exception $e ) { - return new WP_Error( 'error', __( 'Invalid order ID.', 'woocommerce' ) ); + return new WP_Error( 'error', $e->getMessage() ); } return $refund;