Fix unit tests for order and customer functions to provide HPOS compat. (#36905)

This commit is contained in:
Vedanshu Jain 2023-03-08 15:51:06 +05:30 committed by GitHub
commit 9b8a9eb0aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 421 additions and 212 deletions

View File

@ -0,0 +1,4 @@
Significance: patch
Type: fix
Add HPOS compat for admin report functions.

View File

@ -0,0 +1,4 @@
Significance: patch
Type: fix
Add support for `after`, `before`, `modified_after` and `modified_before` params in local timezone.

View File

@ -0,0 +1,5 @@
Significance: patch
Type: fix
Comment: Changes are only in unit tests (for HPOS compat).

View File

@ -0,0 +1,5 @@
Significance: patch
Type: fix
Comment: Skipping unit test for legacy widgets when in HPOS context.

View File

@ -0,0 +1,5 @@
Significance: patch
Type: fix
Comment: Changes are only in unit tests, no functionality is affected.

View File

@ -0,0 +1,4 @@
Significance: patch
Type: fix
Add HPOS compat for wc-user-functions.php.

View File

@ -54,6 +54,7 @@ class WC_Post_Data {
add_action( 'wp_trash_post', array( __CLASS__, 'trash_post' ) ); add_action( 'wp_trash_post', array( __CLASS__, 'trash_post' ) );
add_action( 'untrashed_post', array( __CLASS__, 'untrash_post' ) ); add_action( 'untrashed_post', array( __CLASS__, 'untrash_post' ) );
add_action( 'before_delete_post', array( __CLASS__, 'before_delete_order' ) ); add_action( 'before_delete_post', array( __CLASS__, 'before_delete_order' ) );
add_action( 'woocommerce_before_delete_order', array( __CLASS__, 'before_delete_order' ) );
// Meta cache flushing. // Meta cache flushing.
add_action( 'updated_post_meta', array( __CLASS__, 'flush_object_meta_cache' ), 10, 4 ); add_action( 'updated_post_meta', array( __CLASS__, 'flush_object_meta_cache' ), 10, 4 );

View File

@ -413,6 +413,89 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
return $items; return $items;
} }
/**
* Return the order type of a given item which belongs to WC_Order.
*
* @since 3.2.0
* @param WC_Order $order Order Object.
* @param int $order_item_id Order item id.
* @return string Order Item type
*/
public function get_order_item_type( $order, $order_item_id ) {
global $wpdb;
return $wpdb->get_var( $wpdb->prepare( "SELECT DISTINCT order_item_type FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id = %d and order_item_id = %d;", $order->get_id(), $order_item_id ) );
}
/**
* Prime following caches:
* 1. item-$order_item_id For individual items.
* 2. order-items-$order-id For fetching items associated with an order.
* 3. order-item meta.
*
* @param array $order_ids Order Ids to prime cache for.
* @param array $query_vars Query vars for the query.
*/
protected function prime_order_item_caches_for_orders( $order_ids, $query_vars ) {
global $wpdb;
if ( isset( $query_vars['fields'] ) && 'all' !== $query_vars['fields'] ) {
$line_items = array(
'line_items',
'shipping_lines',
'fee_lines',
'coupon_lines',
);
if ( is_array( $query_vars['fields'] ) && 0 === count( array_intersect( $line_items, $query_vars['fields'] ) ) ) {
return;
}
}
$cache_keys = array_map(
function ( $order_id ) {
return 'order-items-' . $order_id;
},
$order_ids
);
$cache_values = wc_cache_get_multiple( $cache_keys, 'orders' );
$non_cached_ids = array();
foreach ( $order_ids as $order_id ) {
if ( false === $cache_values[ 'order-items-' . $order_id ] ) {
$non_cached_ids[] = $order_id;
}
}
if ( empty( $non_cached_ids ) ) {
return;
}
$non_cached_ids = esc_sql( $non_cached_ids );
$non_cached_ids_string = implode( ',', $non_cached_ids );
$order_items = $wpdb->get_results(
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
"SELECT order_item_type, order_item_id, order_id, order_item_name FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id in ( $non_cached_ids_string ) ORDER BY order_item_id;"
);
if ( empty( $order_items ) ) {
return;
}
$order_items_for_all_orders = array_reduce(
$order_items,
function ( $order_items_collection, $order_item ) {
if ( ! isset( $order_items_collection[ $order_item->order_id ] ) ) {
$order_items_collection[ $order_item->order_id ] = array();
}
$order_items_collection[ $order_item->order_id ][] = $order_item;
return $order_items_collection;
}
);
foreach ( $order_items_for_all_orders as $order_id => $items ) {
wp_cache_set( 'order-items-' . $order_id, $items, 'orders' );
}
foreach ( $order_items as $item ) {
wp_cache_set( 'item-' . $item->order_item_id, $item, 'order-items' );
}
$order_item_ids = wp_list_pluck( $order_items, 'order_item_id' );
update_meta_cache( 'order_item', $order_item_ids );
}
/** /**
* Remove all line items (products, coupons, shipping, taxes) from the order. * Remove all line items (products, coupons, shipping, taxes) from the order.
* *

View File

@ -1118,76 +1118,6 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
} }
} }
/**
* Prime following caches:
* 1. item-$order_item_id For individual items.
* 2. order-items-$order-id For fetching items associated with an order.
* 3. order-item meta.
*
* @param array $order_ids Order Ids to prime cache for.
* @param array $query_vars Query vars for the query.
*/
private function prime_order_item_caches_for_orders( $order_ids, $query_vars ) {
global $wpdb;
if ( isset( $query_vars['fields'] ) && 'all' !== $query_vars['fields'] ) {
$line_items = array(
'line_items',
'shipping_lines',
'fee_lines',
'coupon_lines',
);
if ( is_array( $query_vars['fields'] ) && 0 === count( array_intersect( $line_items, $query_vars['fields'] ) ) ) {
return;
}
}
$cache_keys = array_map(
function ( $order_id ) {
return 'order-items-' . $order_id;
},
$order_ids
);
$cache_values = wc_cache_get_multiple( $cache_keys, 'orders' );
$non_cached_ids = array();
foreach ( $order_ids as $order_id ) {
if ( false === $cache_values[ 'order-items-' . $order_id ] ) {
$non_cached_ids[] = $order_id;
}
}
if ( empty( $non_cached_ids ) ) {
return;
}
$non_cached_ids = esc_sql( $non_cached_ids );
$non_cached_ids_string = implode( ',', $non_cached_ids );
$order_items = $wpdb->get_results(
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
"SELECT order_item_type, order_item_id, order_id, order_item_name FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id in ( $non_cached_ids_string ) ORDER BY order_item_id;"
);
if ( empty( $order_items ) ) {
return;
}
$order_items_for_all_orders = array_reduce(
$order_items,
function ( $order_items_collection, $order_item ) {
if ( ! isset( $order_items_collection[ $order_item->order_id ] ) ) {
$order_items_collection[ $order_item->order_id ] = array();
}
$order_items_collection[ $order_item->order_id ][] = $order_item;
return $order_items_collection;
}
);
foreach ( $order_items_for_all_orders as $order_id => $items ) {
wp_cache_set( 'order-items-' . $order_id, $items, 'orders' );
}
foreach ( $order_items as $item ) {
wp_cache_set( 'item-' . $item->order_item_id, $item, 'order-items' );
}
$order_item_ids = wp_list_pluck( $order_items, 'order_item_id' );
update_meta_cache( 'order_item', $order_item_ids );
}
/** /**
* Prime cache for raw meta data for orders in bulk. Difference between this and WP built-in metadata is that this method also fetches `meta_id` field which we use and cache it. * Prime cache for raw meta data for orders in bulk. Difference between this and WP built-in metadata is that this method also fetches `meta_id` field which we use and cache it.
* *
@ -1240,17 +1170,4 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
); );
WC_Order::prime_raw_meta_data_cache( $raw_meta_data_collection, 'orders' ); WC_Order::prime_raw_meta_data_cache( $raw_meta_data_collection, 'orders' );
} }
/**
* Return the order type of a given item which belongs to WC_Order.
*
* @since 3.2.0
* @param WC_Order $order Order Object.
* @param int $order_item_id Order item id.
* @return string Order Item type
*/
public function get_order_item_type( $order, $order_item_id ) {
global $wpdb;
return $wpdb->get_var( $wpdb->prepare( "SELECT DISTINCT order_item_type FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id = %d and order_item_id = %d;", $order->get_id(), $order_item_id ) );
}
} }

View File

@ -325,6 +325,29 @@ class WC_REST_Orders_V2_Controller extends WC_REST_CRUD_Controller {
return $result; return $result;
} }
/**
* With HPOS, few internal meta keys such as _billing_address_index, _shipping_address_index are not considered internal anymore (since most internal keys were flattened into dedicated columns).
*
* This function helps in filtering out any remaining internal meta keys with HPOS is enabled.
*
* @param array $meta_data Order meta data.
*
* @return array Filtered order meta data.
*/
private function filter_internal_meta_keys( $meta_data ) {
if ( ! OrderUtil::custom_orders_table_usage_is_enabled() ) {
return $meta_data;
}
$cpt_hidden_keys = ( new \WC_Order_Data_Store_CPT() )->get_internal_meta_keys();
$meta_data = array_filter(
$meta_data,
function ( $meta ) use ( $cpt_hidden_keys ) {
return ! in_array( $meta->key, $cpt_hidden_keys, true );
}
);
return array_values( $meta_data );
}
/** /**
* Get formatted item data. * Get formatted item data.
* *
@ -369,6 +392,7 @@ class WC_REST_Orders_V2_Controller extends WC_REST_CRUD_Controller {
case 'meta_data': case 'meta_data':
$meta_data = $order->get_meta_data(); $meta_data = $order->get_meta_data();
$data['meta_data'] = $this->get_meta_data_for_response( $this->request, $meta_data ); $data['meta_data'] = $this->get_meta_data_for_response( $this->request, $meta_data );
$data['meta_data'] = $this->filter_internal_meta_keys( $data['meta_data'] );
break; break;
case 'line_items': case 'line_items':
$data['line_items'] = $order->get_items( 'line_item' ); $data['line_items'] = $order->get_items( 'line_item' );

View File

@ -235,33 +235,6 @@ class WC_REST_Orders_Controller extends WC_REST_Orders_V2_Controller {
} }
} }
/**
* Get formatted item data.
*
* @param WC_Order $order WC_Data instance.
* @return array
*/
protected function get_formatted_item_data( $order ) {
$item_data = parent::get_formatted_item_data( $order );
$cpt_hidden_keys = array();
if ( OrderUtil::custom_orders_table_usage_is_enabled() ) {
$cpt_hidden_keys = ( new \WC_Order_Data_Store_CPT() )->get_internal_meta_keys();
}
// XXX: This might be removed once we finalize the design for internal keys vs meta vs props in COT.
if ( ! empty( $item_data['meta_data'] ) ) {
$item_data['meta_data'] = array_filter(
$item_data['meta_data'],
function( $meta ) use ( $cpt_hidden_keys ) {
return ! in_array( $meta->key, $cpt_hidden_keys, true );
}
);
}
return $item_data;
}
/** /**
* Prepare objects query. * Prepare objects query.
* *

View File

@ -714,16 +714,40 @@ function wc_get_customer_order_count( $user_id ) {
function wc_reset_order_customer_id_on_deleted_user( $user_id ) { function wc_reset_order_customer_id_on_deleted_user( $user_id ) {
global $wpdb; global $wpdb;
$wpdb->update( if ( OrderUtil::custom_orders_table_usage_is_enabled() ) {
$wpdb->postmeta, $order_table_ds = wc_get_container()->get( OrdersTableDataStore::class );
array( $order_table = $order_table_ds::get_orders_table_name();
'meta_value' => 0, $wpdb->update(
), $order_table,
array( array(
'meta_key' => '_customer_user', 'customer_id' => 0,
'meta_value' => $user_id, 'date_updated_gmt' => current_time( 'mysql', true ),
) ),
); // WPCS: slow query ok. array(
'customer_id' => $user_id,
),
array(
'%d',
'%s',
),
array(
'%d',
)
);
}
if ( ! OrderUtil::custom_orders_table_usage_is_enabled() || OrderUtil::is_custom_order_tables_in_sync() ) {
$wpdb->update(
$wpdb->postmeta,
array(
'meta_value' => 0, //phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
),
array(
'meta_key' => '_customer_user', //phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
'meta_value' => $user_id, //phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
)
);
}
} }
add_action( 'deleted_user', 'wc_reset_order_customer_id_on_deleted_user' ); add_action( 'deleted_user', 'wc_reset_order_customer_id_on_deleted_user' );

View File

@ -10,6 +10,8 @@ namespace Automattic\WooCommerce\Admin\API;
defined( 'ABSPATH' ) || exit; defined( 'ABSPATH' ) || exit;
use Automattic\WooCommerce\Admin\API\Reports\Controller as ReportsController; use Automattic\WooCommerce\Admin\API\Reports\Controller as ReportsController;
use Automattic\WooCommerce\Internal\DataStores\Orders\OrdersTableDataStore;
use Automattic\WooCommerce\Utilities\OrderUtil;
/** /**
* Orders controller. * Orders controller.
@ -54,30 +56,61 @@ class Orders extends \WC_REST_Orders_Controller {
* @return array * @return array
*/ */
protected function prepare_objects_query( $request ) { protected function prepare_objects_query( $request ) {
global $wpdb;
$args = parent::prepare_objects_query( $request ); $args = parent::prepare_objects_query( $request );
// Search by partial order number.
if ( ! empty( $request['number'] ) ) { if ( ! empty( $request['number'] ) ) {
$partial_number = trim( $request['number'] ); $args = $this->search_partial_order_number( $request['number'], $args );
$limit = intval( $args['posts_per_page'] ); }
$order_ids = $wpdb->get_col(
return $args;
}
/**
* Helper method to allow searching by partial order number.
*
* @param int $number Partial order number match.
* @param array $args List of arguments for the request.
*
* @return array Modified args with partial order search included.
*/
private function search_partial_order_number( $number, $args ) {
global $wpdb;
$partial_number = trim( $number );
$limit = intval( $args['posts_per_page'] );
if ( OrderUtil::custom_orders_table_usage_is_enabled() ) {
$order_table_name = OrdersTableDataStore::get_orders_table_name();
// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- $orders_table_name is hardcoded.
$order_ids = $wpdb->get_col(
$wpdb->prepare( $wpdb->prepare(
"SELECT ID "SELECT id
FROM {$wpdb->prefix}posts FROM $order_table_name
WHERE post_type = 'shop_order' WHERE type = 'shop_order'
AND ID LIKE %s AND id LIKE %s
LIMIT %d", LIMIT %d",
$wpdb->esc_like( absint( $partial_number ) ) . '%', $wpdb->esc_like( absint( $partial_number ) ) . '%',
$limit $limit
) )
); );
// phpcs:enable
// Force WP_Query return empty if don't found any order. } else {
$order_ids = empty( $order_ids ) ? array( 0 ) : $order_ids; $order_ids = $wpdb->get_col(
$args['post__in'] = $order_ids; $wpdb->prepare(
"SELECT ID
FROM {$wpdb->prefix}posts
WHERE post_type = 'shop_order'
AND ID LIKE %s
LIMIT %d",
$wpdb->esc_like( absint( $partial_number ) ) . '%',
$limit
)
);
} }
// Force WP_Query return empty if don't found any order.
$order_ids = empty( $order_ids ) ? array( 0 ) : $order_ids;
$args['post__in'] = $order_ids;
return $args; return $args;
} }

View File

@ -105,6 +105,7 @@ class DataStore extends ReportsDataStore implements DataStoreInterface {
* Set up all the hooks for maintaining and populating table data. * Set up all the hooks for maintaining and populating table data.
*/ */
public static function init() { public static function init() {
add_action( 'woocommerce_before_delete_order', array( __CLASS__, 'delete_order' ) );
add_action( 'delete_post', array( __CLASS__, 'delete_order' ) ); add_action( 'delete_post', array( __CLASS__, 'delete_order' ) );
} }

View File

@ -202,7 +202,7 @@ class OrdersTableQuery {
// WP_Query legacy. // WP_Query legacy.
'post_date' => 'date_created', 'post_date' => 'date_created',
'post_date_gmt' => 'date_created_gmt', 'post_date_gmt' => 'date_created_gmt',
'post_modified' => 'date_modified', 'post_modified' => 'date_updated',
'post_modified_gmt' => 'date_updated_gmt', 'post_modified_gmt' => 'date_updated_gmt',
'post_status' => 'status', 'post_status' => 'status',
'_date_completed' => 'date_completed', '_date_completed' => 'date_completed',
@ -270,6 +270,15 @@ class OrdersTableQuery {
$this->args['meta_query'] = array( $shortcut_meta_query ); // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query $this->args['meta_query'] = array( $shortcut_meta_query ); // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
} }
} }
// Date query.
if ( isset( $this->args['date_query'] ) && is_array( $this->args['date_query'] ) ) {
foreach ( $this->args['date_query'] as $index => $query ) {
if ( isset( $query['column'] ) && isset( $mapping[ $query['column'] ] ) ) {
$this->args['date_query'][ $index ]['column'] = $mapping[ $query['column'] ];
}
}
}
} }
/** /**
@ -327,7 +336,28 @@ class OrdersTableQuery {
$gmt_date_keys = array_values( $local_to_gmt_date_keys ); $gmt_date_keys = array_values( $local_to_gmt_date_keys );
$local_date_keys = array_keys( $local_to_gmt_date_keys ); $local_date_keys = array_keys( $local_to_gmt_date_keys );
foreach ( array_filter( array_merge( $gmt_date_keys, $local_date_keys ), array( $this, 'arg_isset' ) ) as $date_key ) { $valid_date_keys = array_merge( $gmt_date_keys, $local_date_keys );
$date_keys = array_filter( $valid_date_keys, array( $this, 'arg_isset' ) );
// Process already passed date queries args.
if ( $this->arg_isset( 'date_query' ) && is_array( $this->args['date_query'] ) ) {
foreach ( $this->args['date_query'] as $index => $query ) {
if ( ! isset( $query['column'] ) || ! in_array( $query['column'], $valid_date_keys, true ) ) {
unset( $this->args['date_query'][ $index ] );
continue;
}
// Convert any local dates to GMT.
if ( isset( $local_to_gmt_date_keys[ $query['column'] ] ) ) {
$this->args['date_query'][ $index ]['column'] = $local_to_gmt_date_keys[ $query['column'] ];
$op = isset( $query['after'] ) ? 'after' : 'before';
$date_value_local = $query[ $op ];
$date_value_gmt = wc_string_to_timestamp( get_gmt_from_date( wc_string_to_datetime( $date_value_local ) ) );
$this->args['date_query'][ $index ][ $op ] = $this->date_to_date_query_arg( $date_value_gmt, 'UTC' );
}
}
}
foreach ( $date_keys as $date_key ) {
$date_value = $this->args[ $date_key ]; $date_value = $this->args[ $date_key ];
$operator = '='; $operator = '=';
$dates = array(); $dates = array();
@ -873,6 +903,9 @@ class OrdersTableQuery {
$ids[] = absint( $value ); $ids[] = absint( $value );
} elseif ( is_string( $value ) && is_email( $value ) ) { } elseif ( is_string( $value ) && is_email( $value ) ) {
$emails[] = sanitize_email( $value ); $emails[] = sanitize_email( $value );
} else {
// Invalid query.
$pieces[] = '1=0';
} }
} }

View File

@ -7,6 +7,7 @@
use Automattic\WooCommerce\Proxies\LegacyProxy; use Automattic\WooCommerce\Proxies\LegacyProxy;
use Automattic\WooCommerce\Testing\Tools\CodeHacking\CodeHacker; use Automattic\WooCommerce\Testing\Tools\CodeHacking\CodeHacker;
use Automattic\WooCommerce\Utilities\OrderUtil;
use PHPUnit\Framework\Constraint\IsType; use PHPUnit\Framework\Constraint\IsType;
/** /**
@ -388,4 +389,15 @@ class WC_Unit_Test_Case extends WP_HTTP_TestCase {
$events = self::get_tracks_events( $event_name ); $events = self::get_tracks_events( $event_name );
$this->assertEmpty( $events ); $this->assertEmpty( $events );
} }
/**
* Mark test skipped when HPOS is enabled.
*
* @param string $message Message to display when test is skipped.
*/
protected function skip_if_hpos_enabled( $message ) {
if ( OrderUtil::custom_orders_table_usage_is_enabled() ) {
$this->markTestSkipped( $message );
}
}
} }

View File

@ -37,6 +37,7 @@ class WC_Tests_Admin_Dashboard extends WC_Unit_Test_Case {
* Test: get_status_widget * Test: get_status_widget
*/ */
public function test_status_widget() { public function test_status_widget() {
$this->skip_if_hpos_enabled( 'We don\'t support legacy reports on HPOS' );
wp_set_current_user( $this->user ); wp_set_current_user( $this->user );
$order = WC_Helper_Order::create_order(); $order = WC_Helper_Order::create_order();
$order->set_status( 'completed' ); $order->set_status( 'completed' );
@ -58,6 +59,7 @@ class WC_Tests_Admin_Dashboard extends WC_Unit_Test_Case {
* Test: get_status_widget with woo admin disabled. * Test: get_status_widget with woo admin disabled.
*/ */
public function test_status_widget_with_woo_admin_disabled() { public function test_status_widget_with_woo_admin_disabled() {
$this->skip_if_hpos_enabled( 'We don\'t support legacy reports on HPOS' );
wp_set_current_user( $this->user ); wp_set_current_user( $this->user );
$order = WC_Helper_Order::create_order(); $order = WC_Helper_Order::create_order();
$order->set_status( 'completed' ); $order->set_status( 'completed' );

View File

@ -18,6 +18,16 @@ class WC_Tests_Admin_Report extends WC_Unit_Test_Case {
include_once WC_Unit_Tests_Bootstrap::instance()->plugin_dir . '/includes/admin/reports/class-wc-admin-report.php'; include_once WC_Unit_Tests_Bootstrap::instance()->plugin_dir . '/includes/admin/reports/class-wc-admin-report.php';
} }
/**
* Set up the test.
*/
public function setUp(): void {
parent::setUp();
if ( \Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled() ) {
$this->markTestSkipped( 'This test is not compatible with the custom orders table.' );
}
}
/** /**
* Clear cached report data. * Clear cached report data.
* *

View File

@ -18,6 +18,16 @@ class WC_Tests_Report_Sales_By_Date extends WC_Unit_Test_Case {
include_once WC_Unit_Tests_Bootstrap::instance()->plugin_dir . '/includes/admin/reports/class-wc-report-sales-by-date.php'; include_once WC_Unit_Tests_Bootstrap::instance()->plugin_dir . '/includes/admin/reports/class-wc-report-sales-by-date.php';
} }
/**
* Set up the test.
*/
public function setUp(): void {
parent::setUp();
if ( \Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled() ) {
$this->markTestSkipped( 'This test is not compatible with the custom orders table.' );
}
}
/** /**
* Clear cached report data. * Clear cached report data.
* *

View File

@ -1,4 +1,7 @@
<?php <?php
use Automattic\WooCommerce\Utilities\OrderUtil;
/** /**
* Test meta for https://github.com/woocommerce/woocommerce/issues/13533. * Test meta for https://github.com/woocommerce/woocommerce/issues/13533.
* *
@ -106,11 +109,14 @@ class WC_Tests_CRUD_Meta_Data extends WC_Unit_Test_Case {
$this->assertCount( 1, $order->get_meta_data() ); $this->assertCount( 1, $order->get_meta_data() );
$this->assertTrue( in_array( 'random', wp_list_pluck( $order->get_meta_data(), 'key' ) ) ); $this->assertTrue( in_array( 'random', wp_list_pluck( $order->get_meta_data(), 'key' ) ) );
// The new $order should have 3 items of meta since it's freshly loaded. $expected_count = OrderUtil::custom_orders_table_usage_is_enabled() ? 2 : 3;
$this->assertCount( 3, $new_order->get_meta_data() ); // The new $order should have 3 items (or 2 in case of HPOS since direct post updates are not read) of meta since it's freshly loaded.
$this->assertCount( $expected_count, $new_order->get_meta_data() );
$this->assertTrue( in_array( 'random', wp_list_pluck( $new_order->get_meta_data(), 'key' ) ) ); $this->assertTrue( in_array( 'random', wp_list_pluck( $new_order->get_meta_data(), 'key' ) ) );
$this->assertTrue( in_array( 'random_other', wp_list_pluck( $new_order->get_meta_data(), 'key' ) ) ); $this->assertTrue( in_array( 'random_other', wp_list_pluck( $new_order->get_meta_data(), 'key' ) ) );
$this->assertTrue( in_array( 'random_other_pre_crud', wp_list_pluck( $new_order->get_meta_data(), 'key' ) ) ); if ( ! OrderUtil::custom_orders_table_usage_is_enabled() ) {
$this->assertTrue( in_array( 'random_other_pre_crud', wp_list_pluck( $new_order->get_meta_data(), 'key' ), true ) );
}
} }
/** /**

View File

@ -5,6 +5,8 @@
* @package WooCommerce\Tests\CRUD * @package WooCommerce\Tests\CRUD
*/ */
use Automattic\WooCommerce\Utilities\OrderUtil;
/** /**
* Meta * Meta
* *
@ -882,10 +884,10 @@ class WC_Tests_CRUD_Orders extends WC_Unit_Test_Case {
$object = new WC_Order(); $object = new WC_Order();
// Save + create. // Save + create.
$save_id = $object->save(); $save_id = $object->save();
$post = get_post( $save_id ); $post = get_post( $save_id );
$this->assertEquals( 'shop_order', $post->post_type ); $expected_post_type = OrderUtil::custom_orders_table_usage_is_enabled() ? 'shop_order_placehold' : 'shop_order';
$this->assertEquals( 'shop_order', $post->post_type ); $this->assertEquals( $expected_post_type, $post->post_type );
// Update. // Update.
$update_id = $object->save(); $update_id = $object->save();

View File

@ -109,15 +109,19 @@ class WC_Tests_Order_Functions extends WC_Unit_Test_Case {
->will( $this->returnValueMap( $test_counts[ $order_type ] ) ); ->will( $this->returnValueMap( $test_counts[ $order_type ] ) );
} }
$add_mock_datastores = function( $stores ) use ( $mock_datastores ) { $add_mock_datastores = function ( $stores ) use ( $mock_datastores ) {
return array_merge( $stores, $mock_datastores ); return array_merge( $stores, $mock_datastores );
}; };
$add_mock_order_type = function( $order_types ) use ( $mock_datastores ) { $add_mock_order_type = function ( $order_types ) use ( $mock_datastores ) {
return array( 'shop_order', 'order-fake-type' ); return array( 'shop_order', 'order-fake-type' );
}; };
$return_mock_order_data_store = function ( $stores ) use ( $mock_datastores ) {
return $mock_datastores['order'];
};
add_filter( 'woocommerce_data_stores', $add_mock_datastores ); add_filter( 'woocommerce_data_stores', $add_mock_datastores );
add_filter( 'wc_order_types', $add_mock_order_type ); add_filter( 'wc_order_types', $add_mock_order_type );
add_filter( 'woocommerce_order_data_store', $return_mock_order_data_store, 1000, 2 );
// Check counts for specific order types. // Check counts for specific order types.
$this->assertEquals( 2, wc_orders_count( 'on-hold', 'shop_order' ) ); $this->assertEquals( 2, wc_orders_count( 'on-hold', 'shop_order' ) );
@ -131,6 +135,7 @@ class WC_Tests_Order_Functions extends WC_Unit_Test_Case {
remove_filter( 'woocommerce_data_stores', $add_mock_datastores ); remove_filter( 'woocommerce_data_stores', $add_mock_datastores );
remove_filter( 'wc_order_types', $add_mock_order_type ); remove_filter( 'wc_order_types', $add_mock_order_type );
remove_filter( 'woocommerce_order_data_store', $return_mock_order_data_store, 1000 );
// Confirm that everything's back to normal. // Confirm that everything's back to normal.
wp_cache_flush(); wp_cache_flush();
@ -190,7 +195,8 @@ class WC_Tests_Order_Functions extends WC_Unit_Test_Case {
// Assert the return when $the_order args is false. // Assert the return when $the_order args is false.
$this->assertFalse( wc_get_order( false ) ); $this->assertFalse( wc_get_order( false ) );
$post = get_post( $order->get_id() ); $post = get_post( $order->get_id() );
$theorder = $order;
$this->assertInstanceOf( $this->assertInstanceOf(
'WC_Order', 'WC_Order',
wc_get_order(), wc_get_order(),

View File

@ -10,6 +10,9 @@
* @package WooCommerce\Tests\API * @package WooCommerce\Tests\API
*/ */
use Automattic\WooCommerce\Internal\DataStores\Orders\OrdersTableDataStore;
use Automattic\WooCommerce\Utilities\OrderUtil;
/** /**
* Trait for testing the date filtering on controllers that inherit from WC_REST_CRUD_Controller. * Trait for testing the date filtering on controllers that inherit from WC_REST_CRUD_Controller.
*/ */
@ -34,18 +37,34 @@ trait DateFilteringForCrudControllers {
public function test_filter_by_creation_or_modification_date( $param_name, $filter_by_gmt, $expected_to_be_returned ) { public function test_filter_by_creation_or_modification_date( $param_name, $filter_by_gmt, $expected_to_be_returned ) {
global $wpdb; global $wpdb;
$timezone_string_option = get_option( 'timezone_string' );
update_option( 'timezone_string', 'Africa/Blantyre', true ); // +02:00
wp_set_current_user( $this->user ); wp_set_current_user( $this->user );
$item_id = $this->get_item_for_date_filtering_tests()->get_id(); $item = $this->get_item_for_date_filtering_tests();
$item_id = $item->get_id();
// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared if ( $item instanceof WC_Abstract_Order && OrderUtil::custom_orders_table_usage_is_enabled() ) {
$wpdb->query( $wpdb->update(
'UPDATE ' . $wpdb->prefix . "posts SET OrdersTableDataStore::get_orders_table_name(),
array(
'date_created_gmt' => '2000-01-01T10:00:00',
'date_updated_gmt' => '2000-02-01T10:00:00',
),
array(
'id' => $item->get_id(),
)
);
} else {
// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared
$wpdb->query(
'UPDATE ' . $wpdb->prefix . "posts SET
post_date = '2000-01-01T12:00:00', post_date = '2000-01-01T12:00:00',
post_date_gmt = '2000-01-01T10:00:00', post_date_gmt = '2000-01-01T10:00:00',
post_modified = '2000-02-01T12:00:00', post_modified = '2000-02-01T12:00:00',
post_modified_gmt = '2000-02-01T10:00:00' post_modified_gmt = '2000-02-01T10:00:00'
WHERE ID = " . $item_id WHERE ID = " . $item_id
); );
}
// phpcs:enable WordPress.DB.PreparedSQL.NotPrepared // phpcs:enable WordPress.DB.PreparedSQL.NotPrepared
$request = new WP_REST_Request( 'GET', $this->get_endpoint_for_date_filtering_tests() ); $request = new WP_REST_Request( 'GET', $this->get_endpoint_for_date_filtering_tests() );
@ -60,6 +79,7 @@ trait DateFilteringForCrudControllers {
$this->assertEquals( 200, $response->get_status() ); $this->assertEquals( 200, $response->get_status() );
$this->assertEquals( $expected_to_be_returned ? 1 : 0, count( $response_items ) ); $this->assertEquals( $expected_to_be_returned ? 1 : 0, count( $response_items ) );
update_option( 'timezone_string', $timezone_string_option );
} }
/** /**
@ -80,19 +100,35 @@ trait DateFilteringForCrudControllers {
public function test_can_filter_by_more_than_one_date( $first_param_name, $first_param_value, $second_param_name, $second_param_value, $filter_by_gmt, $expected_to_be_returned ) { public function test_can_filter_by_more_than_one_date( $first_param_name, $first_param_value, $second_param_name, $second_param_value, $filter_by_gmt, $expected_to_be_returned ) {
global $wpdb; global $wpdb;
$timezone_string_option = get_option( 'timezone_string' );
update_option( 'timezone_string', 'Africa/Blantyre', true ); // +02:00
wp_set_current_user( $this->user ); wp_set_current_user( $this->user );
$item_id = $this->get_item_for_date_filtering_tests()->get_id(); $item = $this->get_item_for_date_filtering_tests();
$item_id = $item->get_id();
// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared if ( $item instanceof WC_Abstract_Order && OrderUtil::custom_orders_table_usage_is_enabled() ) {
$wpdb->query( $wpdb->update(
'UPDATE ' . $wpdb->prefix . "posts SET OrdersTableDataStore::get_orders_table_name(),
array(
'date_created_gmt' => '2000-01-01T10:00:00',
'date_updated_gmt' => '2000-02-01T10:00:00',
),
array(
'id' => $item->get_id(),
)
);
} else {
// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared
$wpdb->query(
'UPDATE ' . $wpdb->prefix . "posts SET
post_date = '2000-01-01T12:00:00', post_date = '2000-01-01T12:00:00',
post_date_gmt = '2000-01-01T10:00:00', post_date_gmt = '2000-01-01T10:00:00',
post_modified = '2000-02-01T12:00:00', post_modified = '2000-02-01T12:00:00',
post_modified_gmt = '2000-02-01T10:00:00' post_modified_gmt = '2000-02-01T10:00:00'
WHERE ID = " . $item_id WHERE ID = " . $item_id
); );
// phpcs:enable WordPress.DB.PreparedSQL.NotPrepared // phpcs:enable WordPress.DB.PreparedSQL.NotPrepared
}
$request = new WP_REST_Request( 'GET', $this->get_endpoint_for_date_filtering_tests() ); $request = new WP_REST_Request( 'GET', $this->get_endpoint_for_date_filtering_tests() );
$request->set_query_params( $request->set_query_params(
@ -107,5 +143,6 @@ trait DateFilteringForCrudControllers {
$this->assertEquals( 200, $response->get_status() ); $this->assertEquals( 200, $response->get_status() );
$this->assertEquals( $expected_to_be_returned ? 1 : 0, count( $response_items ) ); $this->assertEquals( $expected_to_be_returned ? 1 : 0, count( $response_items ) );
update_option( 'timezone_string', $timezone_string_option );
} }
} }

View File

@ -323,13 +323,8 @@ class WC_Admin_Tests_API_Reports_Import extends WC_REST_Unit_Test_Case {
// Create 1 draft order - to be excluded from totals. // Create 1 draft order - to be excluded from totals.
$order = WC_Helper_Order::create_order( $this->customer, $product ); $order = WC_Helper_Order::create_order( $this->customer, $product );
$order->set_date_created( time() - ( 5 * DAY_IN_SECONDS ) ); $order->set_date_created( time() - ( 5 * DAY_IN_SECONDS ) );
$order->set_status( 'auto-draft' );
$order->save(); $order->save();
wp_update_post(
array(
'ID' => $order->get_id(),
'post_status' => 'auto-draft',
)
);
// Test totals and total params. // Test totals and total params.
$request = new WP_REST_Request( 'GET', $this->endpoint . '/totals' ); $request = new WP_REST_Request( 'GET', $this->endpoint . '/totals' );

View File

@ -11,11 +11,12 @@ class WC_Customer_Data_Store_Session_Test extends WC_Unit_Test_Case {
* @see https://github.com/woocommerce/woocommerce/issues/28759 * @see https://github.com/woocommerce/woocommerce/issues/28759
* @dataProvider provide_customers_with_different_addresses * @dataProvider provide_customers_with_different_addresses
* *
* @param WC_Customer $customer The customer object being tested. * @param Closure $customer_closure The customer object being tested.
* @param bool $states_should_match If the billing and shipping states should match. * @param bool $states_should_match If the billing and shipping states should match.
* @param bool $countries_should_match If the billing and shipping countries should match. * @param bool $countries_should_match If the billing and shipping countries should match.
*/ */
public function test_setting_default_address_fields( WC_Customer $customer, bool $states_should_match, bool $countries_should_match ) { public function test_setting_default_address_fields( Closure $customer_closure, bool $states_should_match, bool $countries_should_match ) {
$customer = $customer_closure();
$session_data = new WC_Customer_Data_Store_Session(); $session_data = new WC_Customer_Data_Store_Session();
$session_data->read( $customer ); $session_data->read( $customer );
@ -46,66 +47,78 @@ class WC_Customer_Data_Store_Session_Test extends WC_Unit_Test_Case {
* @return array[] * @return array[]
*/ */
public function provide_customers_with_different_addresses() { public function provide_customers_with_different_addresses() {
$has_billing_address_only = new WC_Customer(); $cust1_closure = function () {
$has_billing_address_only->set_email( 'wc-customer-test-01@test.user' ); $has_billing_address_only = new WC_Customer();
$has_billing_address_only->set_billing_address( '1234 Quality Lane' ); $has_billing_address_only->set_email( 'wc-customer-test-01@test.user' );
$has_billing_address_only->set_billing_city( 'Testville' ); $has_billing_address_only->set_billing_address( '1234 Quality Lane' );
$has_billing_address_only->set_billing_country( 'US' ); $has_billing_address_only->set_billing_city( 'Testville' );
$has_billing_address_only->set_billing_state( 'CA' ); $has_billing_address_only->set_billing_country( 'US' );
$has_billing_address_only->set_billing_postcode( '90123' ); $has_billing_address_only->set_billing_state( 'CA' );
$has_billing_address_only->save(); $has_billing_address_only->set_billing_postcode( '90123' );
$has_billing_address_only->save();
return $has_billing_address_only;
};
$separate_billing_and_shipping_state_and_country = new WC_Customer(); $cust2_closure = function () {
$separate_billing_and_shipping_state_and_country->set_email( 'wc-customer-test-02@test.user' ); $separate_billing_and_shipping_state_and_country = new WC_Customer();
$separate_billing_and_shipping_state_and_country->set_billing_address( '4567 Scenario Street' ); $separate_billing_and_shipping_state_and_country->set_email( 'wc-customer-test-02@test.user' );
$separate_billing_and_shipping_state_and_country->set_billing_city( 'Unitly' ); $separate_billing_and_shipping_state_and_country->set_billing_address( '4567 Scenario Street' );
$separate_billing_and_shipping_state_and_country->set_billing_country( 'UK' ); $separate_billing_and_shipping_state_and_country->set_billing_city( 'Unitly' );
$separate_billing_and_shipping_state_and_country->set_billing_state( 'Computershire' ); $separate_billing_and_shipping_state_and_country->set_billing_country( 'UK' );
$separate_billing_and_shipping_state_and_country->set_billing_postcode( 'ZX1 2PQ' ); $separate_billing_and_shipping_state_and_country->set_billing_state( 'Computershire' );
$separate_billing_and_shipping_state_and_country->set_shipping_address( '8901 Situation Court' ); $separate_billing_and_shipping_state_and_country->set_billing_postcode( 'ZX1 2PQ' );
$separate_billing_and_shipping_state_and_country->set_shipping_city( 'Endtoendly' ); $separate_billing_and_shipping_state_and_country->set_shipping_address( '8901 Situation Court' );
$separate_billing_and_shipping_state_and_country->set_shipping_country( 'CA' ); $separate_billing_and_shipping_state_and_country->set_shipping_city( 'Endtoendly' );
$separate_billing_and_shipping_state_and_country->set_shipping_state( 'BC' ); $separate_billing_and_shipping_state_and_country->set_shipping_country( 'CA' );
$separate_billing_and_shipping_state_and_country->set_shipping_postcode( 'A1B 2C3' ); $separate_billing_and_shipping_state_and_country->set_shipping_state( 'BC' );
$separate_billing_and_shipping_state_and_country->save(); $separate_billing_and_shipping_state_and_country->set_shipping_postcode( 'A1B 2C3' );
$separate_billing_and_shipping_state_and_country->save();
return $separate_billing_and_shipping_state_and_country;
};
$separate_billing_state_same_country = new WC_Customer(); $cust3_closure = function () {
$separate_billing_state_same_country->set_email( 'wc-customer-test-03@test.user' ); $separate_billing_state_same_country = new WC_Customer();
$separate_billing_state_same_country->set_billing_address( '4567 Scenario Street' ); $separate_billing_state_same_country->set_email( 'wc-customer-test-03@test.user' );
$separate_billing_state_same_country->set_billing_city( 'Unitly' ); $separate_billing_state_same_country->set_billing_address( '4567 Scenario Street' );
$separate_billing_state_same_country->set_billing_country( 'UK' ); $separate_billing_state_same_country->set_billing_city( 'Unitly' );
$separate_billing_state_same_country->set_billing_state( 'Computershire' ); $separate_billing_state_same_country->set_billing_country( 'UK' );
$separate_billing_state_same_country->set_billing_postcode( 'ZX1 2PQ' ); $separate_billing_state_same_country->set_billing_state( 'Computershire' );
$separate_billing_state_same_country->set_shipping_address( '8901 Situation Court' ); $separate_billing_state_same_country->set_billing_postcode( 'ZX1 2PQ' );
$separate_billing_state_same_country->set_shipping_city( 'Endtoendly' ); $separate_billing_state_same_country->set_shipping_address( '8901 Situation Court' );
$separate_billing_state_same_country->set_shipping_country( 'UK' ); $separate_billing_state_same_country->set_shipping_city( 'Endtoendly' );
$separate_billing_state_same_country->set_shipping_state( 'Byteshire' ); $separate_billing_state_same_country->set_shipping_country( 'UK' );
$separate_billing_state_same_country->set_shipping_postcode( 'RS1 2TU' ); $separate_billing_state_same_country->set_shipping_state( 'Byteshire' );
$separate_billing_state_same_country->save(); $separate_billing_state_same_country->set_shipping_postcode( 'RS1 2TU' );
$separate_billing_state_same_country->save();
return $separate_billing_state_same_country;
};
$shipping_address_is_effectively_empty = new WC_Customer(); $cust4_closure = function () {
$shipping_address_is_effectively_empty->set_email( 'wc-customer-test-04@test.user' ); $shipping_address_is_effectively_empty = new WC_Customer();
$shipping_address_is_effectively_empty->set_shipping_address( ' ' ); $shipping_address_is_effectively_empty->set_email( 'wc-customer-test-04@test.user' );
$shipping_address_is_effectively_empty->save(); $shipping_address_is_effectively_empty->set_shipping_address( ' ' );
$shipping_address_is_effectively_empty->save();
return $shipping_address_is_effectively_empty;
};
return array( return array(
'has_billing_address_only' => array( 'has_billing_address_only' => array(
$has_billing_address_only, $cust1_closure,
true, true,
true, true,
), ),
'separate_billing_and_shipping_state_and_country' => array( 'separate_billing_and_shipping_state_and_country' => array(
$separate_billing_and_shipping_state_and_country, $cust2_closure,
false, false,
false, false,
), ),
'separate_billing_state_same_country' => array( 'separate_billing_state_same_country' => array(
$separate_billing_state_same_country, $cust3_closure,
false, false,
true, true,
), ),
'shipping_address_is_effectively_empty' => array( 'shipping_address_is_effectively_empty' => array(
$shipping_address_is_effectively_empty, $cust4_closure,
true, true,
true, true,
), ),

View File

@ -29,8 +29,8 @@ class WC_Gateway_Paypal_Test extends \WC_Unit_Test_Case {
$order = WC_Helper_Order::create_order(); $order = WC_Helper_Order::create_order();
$order->save(); $order->save();
update_post_meta( $order->get_id(), '_paypal_status', 'pending' ); $order->update_meta_data( '_paypal_status', 'pending' );
update_post_meta( $order->get_id(), '_transaction_id', $this->transaction_id_26960 ); $order->set_transaction_id( $this->transaction_id_26960 );
$order->set_payment_method( 'paypal' ); $order->set_payment_method( 'paypal' );
$order->save(); $order->save();
@ -56,8 +56,8 @@ class WC_Gateway_Paypal_Test extends \WC_Unit_Test_Case {
$order = WC_Helper_Order::create_order(); $order = WC_Helper_Order::create_order();
$order->save(); $order->save();
update_post_meta( $order->get_id(), '_paypal_status', 'pending' ); $order->update_meta_data( '_paypal_status', 'pending' );
update_post_meta( $order->get_id(), '_transaction_id', $this->transaction_id_26960 ); $order->set_transaction_id( $this->transaction_id_26960 );
$order->set_payment_method( 'paypal' ); $order->set_payment_method( 'paypal' );
$order->save(); $order->save();