Sync order data with cart data when cart is updated from any route (https://github.com/woocommerce/woocommerce-blocks/pull/5379)
* Link order controller to cart routes * Remove order controller from checkout route * Fix PHP warnings in abstract schema * Fix PHP warnings in abstract route * Update shipping phone handling * Includes are handled in core now * Remove maybe_update_order_from_customer * Add cart_updated routine to all cart routes * Remove abstract method * Remove test for woocommerce_blocks_cart_update_order_from_customer_request * Remove do_order_callback
This commit is contained in:
parent
14a45a4380
commit
ecc80e5cff
|
@ -268,11 +268,11 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"name": "woocommerce_blocks_cart_update_order_from_customer_request",
|
||||
"file": "StoreApi/Routes/CartUpdateCustomer.php",
|
||||
"name": "woocommerce_blocks_cart_update_order_from_request",
|
||||
"file": "StoreApi/Routes/AbstractCartRoute.php",
|
||||
"type": "action",
|
||||
"doc": {
|
||||
"description": "Fires when the Checkout Block/Store API updates an existing draft order from customer data.",
|
||||
"description": "Fires when the order is synced with cart data from a cart route.",
|
||||
"long_description": "",
|
||||
"tags": [
|
||||
{
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
- [woocommerce_blocks_cart_enqueue_data](#woocommerce_blocks_cart_enqueue_data)
|
||||
- [woocommerce_blocks_cart_enqueue_data](#woocommerce_blocks_cart_enqueue_data-1)
|
||||
- [woocommerce_blocks_cart_update_customer_from_request](#woocommerce_blocks_cart_update_customer_from_request)
|
||||
- [woocommerce_blocks_cart_update_order_from_customer_request](#woocommerce_blocks_cart_update_order_from_customer_request)
|
||||
- [woocommerce_blocks_cart_update_order_from_request](#woocommerce_blocks_cart_update_order_from_request)
|
||||
- [woocommerce_blocks_checkout_enqueue_data](#woocommerce_blocks_checkout_enqueue_data)
|
||||
- [woocommerce_blocks_checkout_order_processed](#woocommerce_blocks_checkout_order_processed)
|
||||
- [woocommerce_blocks_checkout_update_order_from_request](#woocommerce_blocks_checkout_update_order_from_request)
|
||||
|
@ -261,13 +261,13 @@ File: [StoreApi/Routes/CartUpdateCustomer.php](../src/StoreApi/Routes/CartUpdate
|
|||
|
||||
---
|
||||
|
||||
## woocommerce_blocks_cart_update_order_from_customer_request
|
||||
## woocommerce_blocks_cart_update_order_from_request
|
||||
|
||||
|
||||
Fires when the Checkout Block/Store API updates an existing draft order from customer data.
|
||||
Fires when the order is synced with cart data from a cart route.
|
||||
|
||||
```php
|
||||
do_action( 'woocommerce_blocks_cart_update_order_from_customer_request', \WC_Order $draft_order, \WC_Customer $customer, \WP_REST_Request $request )
|
||||
do_action( 'woocommerce_blocks_cart_update_order_from_request', \WC_Order $draft_order, \WC_Customer $customer, \WP_REST_Request $request )
|
||||
```
|
||||
|
||||
### Parameters
|
||||
|
@ -281,7 +281,7 @@ do_action( 'woocommerce_blocks_cart_update_order_from_customer_request', \WC_Ord
|
|||
### Source
|
||||
|
||||
|
||||
File: [StoreApi/Routes/CartUpdateCustomer.php](../src/StoreApi/Routes/CartUpdateCustomer.php)
|
||||
File: [StoreApi/Routes/AbstractCartRoute.php](../src/StoreApi/Routes/AbstractCartRoute.php)
|
||||
|
||||
---
|
||||
|
||||
|
|
|
@ -4,13 +4,16 @@ namespace Automattic\WooCommerce\Blocks\StoreApi\Routes;
|
|||
use Automattic\WooCommerce\Blocks\StoreApi\Schemas\AbstractSchema;
|
||||
use Automattic\WooCommerce\Blocks\StoreApi\Schemas\CartSchema;
|
||||
use Automattic\WooCommerce\Blocks\StoreApi\Utilities\CartController;
|
||||
|
||||
use Automattic\WooCommerce\Blocks\StoreApi\Utilities\DraftOrderTrait;
|
||||
use Automattic\WooCommerce\Blocks\StoreApi\Utilities\OrderController;
|
||||
/**
|
||||
* Abstract Cart Route
|
||||
*
|
||||
* @internal This API is used internally by Blocks--it is still in flux and may be subject to revisions.
|
||||
*/
|
||||
abstract class AbstractCartRoute extends AbstractRoute {
|
||||
use DraftOrderTrait;
|
||||
|
||||
/**
|
||||
* Schema class for this route's response.
|
||||
*
|
||||
|
@ -32,6 +35,13 @@ abstract class AbstractCartRoute extends AbstractRoute {
|
|||
*/
|
||||
protected $cart_controller;
|
||||
|
||||
/**
|
||||
* Order controller class instance.
|
||||
*
|
||||
* @var OrderController
|
||||
*/
|
||||
protected $order_controller;
|
||||
|
||||
/**
|
||||
* Constructor accepts two types of schema; one for the item being returned, and one for the cart as a whole. These
|
||||
* may be the same depending on the route.
|
||||
|
@ -39,11 +49,13 @@ abstract class AbstractCartRoute extends AbstractRoute {
|
|||
* @param CartSchema $cart_schema Schema class for the cart.
|
||||
* @param AbstractSchema $item_schema Schema class for this route's items if it differs from the cart schema.
|
||||
* @param CartController $cart_controller Cart controller class.
|
||||
* @param OrderController $order_controller Order controller class.
|
||||
*/
|
||||
public function __construct( CartSchema $cart_schema, AbstractSchema $item_schema = null, CartController $cart_controller ) {
|
||||
public function __construct( CartSchema $cart_schema, AbstractSchema $item_schema = null, CartController $cart_controller, OrderController $order_controller ) {
|
||||
$this->schema = is_null( $item_schema ) ? $cart_schema : $item_schema;
|
||||
$this->cart_schema = $cart_schema;
|
||||
$this->cart_controller = $cart_controller;
|
||||
$this->order_controller = $order_controller;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -74,6 +86,8 @@ abstract class AbstractCartRoute extends AbstractRoute {
|
|||
|
||||
if ( is_wp_error( $response ) ) {
|
||||
$response = $this->error_to_response( $response );
|
||||
} elseif ( in_array( $request->get_method(), [ 'POST', 'PUT', 'PATCH', 'DELETE' ], true ) ) {
|
||||
$this->cart_updated( $request );
|
||||
}
|
||||
|
||||
return $this->add_nonce_headers( $response );
|
||||
|
@ -102,6 +116,29 @@ abstract class AbstractCartRoute extends AbstractRoute {
|
|||
return 'GET' !== $request->get_method();
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggered after an update to cart data. Re-calculates totals and updates draft orders (if they already exist) to
|
||||
* keep all data in sync.
|
||||
*
|
||||
* @param \WP_REST_Request $request Request object.
|
||||
*/
|
||||
protected function cart_updated( \WP_REST_Request $request ) {
|
||||
$draft_order = $this->get_draft_order();
|
||||
|
||||
if ( $draft_order ) {
|
||||
$this->order_controller->update_order_from_cart( $draft_order );
|
||||
|
||||
/**
|
||||
* Fires when the order is synced with cart data from a cart route.
|
||||
*
|
||||
* @param \WC_Order $draft_order Order object.
|
||||
* @param \WC_Customer $customer Customer object.
|
||||
* @param \WP_REST_Request $request Full details about the request.
|
||||
*/
|
||||
do_action( 'woocommerce_blocks_cart_update_order_from_request', $draft_order, $request );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the cart totals are calculated before an API response is generated.
|
||||
*/
|
||||
|
|
|
@ -87,8 +87,8 @@ abstract class AbstractRoute implements RouteInterface {
|
|||
/**
|
||||
* Converts an error to a response object. Based on \WP_REST_Server.
|
||||
*
|
||||
* @param WP_Error $error WP_Error instance.
|
||||
* @return WP_REST_Response List of associative arrays with code and message keys.
|
||||
* @param \WP_Error $error WP_Error instance.
|
||||
* @return \WP_REST_Response List of associative arrays with code and message keys.
|
||||
*/
|
||||
protected function error_to_response( $error ) {
|
||||
$error_data = $error->get_error_data();
|
||||
|
|
|
@ -121,7 +121,6 @@ class CartUpdateCustomer extends AbstractCartRoute {
|
|||
$customer->save();
|
||||
|
||||
$this->calculate_totals();
|
||||
$this->maybe_update_order_from_customer( $customer, $request );
|
||||
|
||||
return rest_ensure_response( $this->schema->get_item_response( $cart ) );
|
||||
}
|
||||
|
@ -146,56 +145,4 @@ class CartUpdateCustomer extends AbstractCartRoute {
|
|||
'phone' => $customer->get_billing_phone(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* If there is a draft order, update the customer data within that also so the
|
||||
* cart and order are kept in sync.
|
||||
*
|
||||
* @param \WC_Customer $customer Customer object.
|
||||
* @param \WP_REST_Request $request Request object.
|
||||
*/
|
||||
protected function maybe_update_order_from_customer( \WC_Customer $customer, \WP_REST_Request $request ) {
|
||||
$draft_order = $this->get_draft_order();
|
||||
|
||||
if ( ! $draft_order ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$draft_order->set_props(
|
||||
[
|
||||
'billing_first_name' => $customer->get_billing_first_name(),
|
||||
'billing_last_name' => $customer->get_billing_last_name(),
|
||||
'billing_company' => $customer->get_billing_company(),
|
||||
'billing_address_1' => $customer->get_billing_address_1(),
|
||||
'billing_address_2' => $customer->get_billing_address_2(),
|
||||
'billing_city' => $customer->get_billing_city(),
|
||||
'billing_state' => $customer->get_billing_state(),
|
||||
'billing_postcode' => $customer->get_billing_postcode(),
|
||||
'billing_country' => $customer->get_billing_country(),
|
||||
'billing_email' => $customer->get_billing_email(),
|
||||
'billing_phone' => $customer->get_billing_phone(),
|
||||
'shipping_first_name' => $customer->get_shipping_first_name(),
|
||||
'shipping_last_name' => $customer->get_shipping_last_name(),
|
||||
'shipping_company' => $customer->get_shipping_company(),
|
||||
'shipping_address_1' => $customer->get_shipping_address_1(),
|
||||
'shipping_address_2' => $customer->get_shipping_address_2(),
|
||||
'shipping_city' => $customer->get_shipping_city(),
|
||||
'shipping_state' => $customer->get_shipping_state(),
|
||||
'shipping_postcode' => $customer->get_shipping_postcode(),
|
||||
'shipping_country' => $customer->get_shipping_country(),
|
||||
'shipping_phone' => $customer->get_shipping_phone(),
|
||||
]
|
||||
);
|
||||
|
||||
/**
|
||||
* Fires when the Checkout Block/Store API updates an existing draft order from customer data.
|
||||
*
|
||||
* @param \WC_Order $draft_order Order object.
|
||||
* @param \WC_Customer $customer Customer object.
|
||||
* @param \WP_REST_Request $request Full details about the request.
|
||||
*/
|
||||
do_action( 'woocommerce_blocks_cart_update_order_from_customer_request', $draft_order, $customer, $request );
|
||||
|
||||
$draft_order->save();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@ use Automattic\WooCommerce\Blocks\StoreApi\Utilities\InvalidStockLevelsInCartExc
|
|||
use Automattic\WooCommerce\Blocks\StoreApi\Utilities\OrderController;
|
||||
use Automattic\WooCommerce\Checkout\Helpers\ReserveStock;
|
||||
use Automattic\WooCommerce\Checkout\Helpers\ReserveStockException;
|
||||
|
||||
/**
|
||||
* Checkout class.
|
||||
*
|
||||
|
@ -29,29 +28,6 @@ class Checkout extends AbstractCartRoute {
|
|||
*/
|
||||
private $order = null;
|
||||
|
||||
/**
|
||||
* Order controller class instance.
|
||||
*
|
||||
* @var OrderController
|
||||
*/
|
||||
protected $order_controller;
|
||||
|
||||
/**
|
||||
* Constructor accepts two types of schema; one for the item being returned, and one for the cart as a whole. These
|
||||
* may be the same depending on the route.
|
||||
*
|
||||
* @param CartSchema $cart_schema Schema class for the cart.
|
||||
* @param AbstractSchema $item_schema Schema class for this route's items if it differs from the cart schema.
|
||||
* @param CartController $cart_controller Cart controller class.
|
||||
* @param OrderController $order_controller Order controller class.
|
||||
*/
|
||||
public function __construct( CartSchema $cart_schema, AbstractSchema $item_schema = null, CartController $cart_controller, OrderController $order_controller ) {
|
||||
$this->schema = is_null( $item_schema ) ? $cart_schema : $item_schema;
|
||||
$this->cart_schema = $cart_schema;
|
||||
$this->cart_controller = $cart_controller;
|
||||
$this->order_controller = $order_controller;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the path of this REST route.
|
||||
*
|
||||
|
|
|
@ -75,19 +75,19 @@ class RoutesController {
|
|||
$order_controller = new OrderController();
|
||||
|
||||
$this->routes = [
|
||||
'cart' => new Routes\Cart( $this->schemas->get( 'cart' ), null, $cart_controller ),
|
||||
'cart-add-item' => new Routes\CartAddItem( $this->schemas->get( 'cart' ), null, $cart_controller ),
|
||||
'cart-apply-coupon' => new Routes\CartApplyCoupon( $this->schemas->get( 'cart' ), null, $cart_controller ),
|
||||
'cart-coupons' => new Routes\CartCoupons( $this->schemas->get( 'cart' ), $this->schemas->get( 'cart-coupon' ), $cart_controller ),
|
||||
'cart-coupons-by-code' => new Routes\CartCouponsByCode( $this->schemas->get( 'cart' ), $this->schemas->get( 'cart-coupon' ), $cart_controller ),
|
||||
'cart-extensions' => new Routes\CartExtensions( $this->schemas->get( 'cart' ), $this->schemas->get( 'cart-extensions' ), $cart_controller ),
|
||||
'cart-items' => new Routes\CartItems( $this->schemas->get( 'cart' ), $this->schemas->get( 'cart-item' ), $cart_controller ),
|
||||
'cart-items-by-key' => new Routes\CartItemsByKey( $this->schemas->get( 'cart' ), $this->schemas->get( 'cart-item' ), $cart_controller ),
|
||||
'cart-remove-coupon' => new Routes\CartRemoveCoupon( $this->schemas->get( 'cart' ), null, $cart_controller ),
|
||||
'cart-remove-item' => new Routes\CartRemoveItem( $this->schemas->get( 'cart' ), null, $cart_controller ),
|
||||
'cart-select-shipping-rate' => new Routes\CartSelectShippingRate( $this->schemas->get( 'cart' ), null, $cart_controller ),
|
||||
'cart-update-item' => new Routes\CartUpdateItem( $this->schemas->get( 'cart' ), null, $cart_controller ),
|
||||
'cart-update-customer' => new Routes\CartUpdateCustomer( $this->schemas->get( 'cart' ), null, $cart_controller ),
|
||||
'cart' => new Routes\Cart( $this->schemas->get( 'cart' ), null, $cart_controller, $order_controller ),
|
||||
'cart-add-item' => new Routes\CartAddItem( $this->schemas->get( 'cart' ), null, $cart_controller, $order_controller ),
|
||||
'cart-apply-coupon' => new Routes\CartApplyCoupon( $this->schemas->get( 'cart' ), null, $cart_controller, $order_controller ),
|
||||
'cart-coupons' => new Routes\CartCoupons( $this->schemas->get( 'cart' ), $this->schemas->get( 'cart-coupon' ), $cart_controller, $order_controller ),
|
||||
'cart-coupons-by-code' => new Routes\CartCouponsByCode( $this->schemas->get( 'cart' ), $this->schemas->get( 'cart-coupon' ), $cart_controller, $order_controller ),
|
||||
'cart-extensions' => new Routes\CartExtensions( $this->schemas->get( 'cart' ), $this->schemas->get( 'cart-extensions' ), $cart_controller, $order_controller ),
|
||||
'cart-items' => new Routes\CartItems( $this->schemas->get( 'cart' ), $this->schemas->get( 'cart-item' ), $cart_controller, $order_controller ),
|
||||
'cart-items-by-key' => new Routes\CartItemsByKey( $this->schemas->get( 'cart' ), $this->schemas->get( 'cart-item' ), $cart_controller, $order_controller ),
|
||||
'cart-remove-coupon' => new Routes\CartRemoveCoupon( $this->schemas->get( 'cart' ), null, $cart_controller, $order_controller ),
|
||||
'cart-remove-item' => new Routes\CartRemoveItem( $this->schemas->get( 'cart' ), null, $cart_controller, $order_controller ),
|
||||
'cart-select-shipping-rate' => new Routes\CartSelectShippingRate( $this->schemas->get( 'cart' ), null, $cart_controller, $order_controller ),
|
||||
'cart-update-item' => new Routes\CartUpdateItem( $this->schemas->get( 'cart' ), null, $cart_controller, $order_controller ),
|
||||
'cart-update-customer' => new Routes\CartUpdateCustomer( $this->schemas->get( 'cart' ), null, $cart_controller, $order_controller ),
|
||||
'checkout' => new Routes\Checkout( $this->schemas->get( 'cart' ), $this->schemas->get( 'checkout' ), $cart_controller, $order_controller ),
|
||||
'product-attributes' => new Routes\ProductAttributes( $this->schemas->get( 'product-attribute' ) ),
|
||||
'product-attributes-by-id' => new Routes\ProductAttributesById( $this->schemas->get( 'product-attribute' ) ),
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?php
|
||||
namespace Automattic\WooCommerce\Blocks\StoreApi\Schemas;
|
||||
|
||||
use Automattic\WooCommerce\Blocks\Package;
|
||||
use Automattic\WooCommerce\Blocks\Domain\Services\ExtendRestApi;
|
||||
|
||||
/**
|
||||
* AbstractSchema class.
|
||||
*
|
||||
|
@ -56,6 +56,13 @@ abstract class AbstractSchema {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return schema properties.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
abstract public function get_properties();
|
||||
|
||||
/**
|
||||
* Recursive removal of arg_options.
|
||||
*
|
||||
|
@ -94,7 +101,7 @@ abstract class AbstractSchema {
|
|||
/**
|
||||
* Returns extended data for a specific endpoint.
|
||||
*
|
||||
* @param string $endpoint The endpoint identifer.
|
||||
* @param string $endpoint The endpoint identifier.
|
||||
* @param array ...$passed_args An array of arguments to be passed to callbacks.
|
||||
* @return object the data that will get added.
|
||||
*/
|
||||
|
|
|
@ -23,8 +23,6 @@ class CartController {
|
|||
*/
|
||||
public function load_cart() {
|
||||
if ( ! did_action( 'woocommerce_load_cart_from_session' ) && function_exists( 'wc_load_cart' ) ) {
|
||||
include_once WC_ABSPATH . 'includes/wc-cart-functions.php';
|
||||
include_once WC_ABSPATH . 'includes/wc-notice-functions.php';
|
||||
wc_load_cart();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -505,15 +505,8 @@ class OrderController {
|
|||
'shipping_state' => wc()->customer->get_shipping_state(),
|
||||
'shipping_postcode' => wc()->customer->get_shipping_postcode(),
|
||||
'shipping_country' => wc()->customer->get_shipping_country(),
|
||||
'shipping_phone' => wc()->customer->get_shipping_phone(),
|
||||
]
|
||||
);
|
||||
|
||||
$shipping_phone_value = is_callable( [ wc()->customer, 'get_shipping_phone' ] ) ? wc()->customer->get_shipping_phone() : wc()->customer->get_meta( 'shipping_phone', true );
|
||||
|
||||
if ( is_callable( [ $order, 'set_shipping_phone' ] ) ) {
|
||||
$order->set_shipping_phone( $shipping_phone_value );
|
||||
} else {
|
||||
$order->update_meta_data( '_shipping_phone', $shipping_phone_value );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -188,16 +188,13 @@ class Cart extends ControllerTestCase {
|
|||
|
||||
$action_callback = \Mockery::mock( 'ActionCallback' );
|
||||
$action_callback->shouldReceive( 'do_customer_callback' )->once();
|
||||
$action_callback->shouldReceive( 'do_order_callback' )->once();
|
||||
|
||||
add_action( 'woocommerce_blocks_cart_update_customer_from_request', array( $action_callback, 'do_customer_callback' ) );
|
||||
add_action( 'woocommerce_blocks_cart_update_order_from_customer_request', array( $action_callback, 'do_order_callback' ) );
|
||||
|
||||
$response = rest_get_server()->dispatch( $request );
|
||||
$data = $response->get_data();
|
||||
|
||||
remove_action( 'woocommerce_blocks_cart_update_customer_from_request', array( $action_callback, 'do_customer_callback' ) );
|
||||
remove_action( 'woocommerce_blocks_cart_update_order_from_customer_request', array( $action_callback, 'do_order_callback' ) );
|
||||
|
||||
$this->assertEquals( 200, $response->get_status(), print_r( $response, true ) );
|
||||
$this->assertArrayHasKey( 'shipping_rates', $data );
|
||||
|
|
Loading…
Reference in New Issue