Support `wc_customer_bought_product` for hpos. (#34931)

* Support `wc_customer_bought_product` for hpos.

* Apply code standards.
This commit is contained in:
Vedanshu Jain 2022-10-05 00:22:02 +05:30 committed by GitHub
parent 17c8a7fb0a
commit 82153ea567
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 161 additions and 12 deletions

View File

@ -0,0 +1,4 @@
Significance: patch
Type: add
Support `wc_customer_bought_product` function in HPOS.

View File

@ -8,6 +8,9 @@
* @version 2.2.0
*/
use Automattic\WooCommerce\Internal\DataStores\Orders\OrdersTableDataStore;
use Automattic\WooCommerce\Utilities\OrderUtil;
defined( 'ABSPATH' ) || exit;
/**
@ -344,19 +347,40 @@ function wc_customer_bought_product( $customer_email, $user_id, $product_id ) {
return false;
}
$result = $wpdb->get_col(
"
SELECT im.meta_value FROM {$wpdb->posts} AS p
INNER JOIN {$wpdb->postmeta} AS pm ON p.ID = pm.post_id
INNER JOIN {$wpdb->prefix}woocommerce_order_items AS i ON p.ID = i.order_id
INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS im ON i.order_item_id = im.order_item_id
WHERE p.post_status IN ( 'wc-" . implode( "','wc-", $statuses ) . "' )
AND pm.meta_key IN ( '_billing_email', '_customer_user' )
AND im.meta_key IN ( '_product_id', '_variation_id' )
AND im.meta_value != 0
AND pm.meta_value IN ( '" . implode( "','", $customer_data ) . "' )
if ( OrderUtil::custom_orders_table_usage_is_enabled() ) {
$statuses = array_map(
function ( $status ) {
return "wc-$status";
},
$statuses
);
$order_table = OrdersTableDataStore::get_orders_table_name();
$sql = "
SELECT im.meta_value FROM $order_table AS o
INNER JOIN {$wpdb->prefix}woocommerce_order_items AS i ON o.id = i.order_id
INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS im ON i.order_item_id = im.order_item_id
WHERE o.status IN ('" . implode( "','", $statuses ) . "')
AND im.meta_key IN ('_product_id', '_variation_id' )
AND im.meta_value != 0
AND ( o.customer_id IN ('" . implode( "','", $customer_data ) . "') OR o.billing_email IN ('" . implode( "','", $customer_data ) . "') )
";
$result = $wpdb->get_col( $sql );
} else {
$result = $wpdb->get_col(
"
SELECT im.meta_value FROM {$wpdb->posts} AS p
INNER JOIN {$wpdb->postmeta} AS pm ON p.ID = pm.post_id
INNER JOIN {$wpdb->prefix}woocommerce_order_items AS i ON p.ID = i.order_id
INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS im ON i.order_item_id = im.order_item_id
WHERE p.post_status IN ( 'wc-" . implode( "','wc-", $statuses ) . "' )
AND pm.meta_key IN ( '_billing_email', '_customer_user' )
AND im.meta_key IN ( '_product_id', '_variation_id' )
AND im.meta_value != 0
AND pm.meta_value IN ( '" . implode( "','", $customer_data ) . "' )
"
); // WPCS: unprepared SQL ok.
); // WPCS: unprepared SQL ok.
}
$result = array_map( 'absint', $result );
$transient_value = array(

View File

@ -0,0 +1,60 @@
<?php
namespace Automattic\WooCommerce\RestApi\UnitTests;
use Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController;
use Automattic\WooCommerce\Internal\DataStores\Orders\OrdersTableDataStore;
use Automattic\WooCommerce\Internal\Features\FeaturesController;
use Automattic\WooCommerce\RestApi\UnitTests\Helpers\OrderHelper;
use WC_Data_Store;
/**
* Trait HPOSToggleTrait.
*
* Provides methods to toggle the HPOS feature on and off.
*/
trait HPOSToggleTrait {
/**
* Call in setUp to enable COT/HPOS.
*
* @return void
*/
public function setup_cot() {
// Remove the Test Suites use of temporary tables https://wordpress.stackexchange.com/a/220308.
remove_filter( 'query', array( $this, '_create_temporary_tables' ) );
remove_filter( 'query', array( $this, '_drop_temporary_tables' ) );
OrderHelper::delete_order_custom_tables();
OrderHelper::create_order_custom_table_if_not_exist();
$this->toggle_cot( true );
}
/**
* Call in teardown to disable COT/HPOS.
*/
public function clean_up_cot_setup(): void {
$this->toggle_cot( false );
// Add back removed filter.
add_filter( 'query', array( $this, '_create_temporary_tables' ) );
add_filter( 'query', array( $this, '_drop_temporary_tables' ) );
}
/**
* Enables or disables the custom orders table across WP temporarily.
*
* @param boolean $enabled TRUE to enable COT or FALSE to disable.
* @return void
*/
private function toggle_cot( bool $enabled ): void {
$features_controller = wc_get_container()->get( Featurescontroller::class );
$features_controller->change_feature_enable( 'custom_order_tables', true );
update_option( CustomOrdersTableController::CUSTOM_ORDERS_TABLE_USAGE_ENABLED_OPTION, wc_bool_to_string( $enabled ) );
// Confirm things are really correct.
$wc_data_store = WC_Data_Store::load( 'order' );
assert( is_a( $wc_data_store->get_current_class_name(), OrdersTableDataStore::class, true ) === $enabled );
}
}

View File

@ -0,0 +1,61 @@
<?php
use Automattic\WooCommerce\RestApi\UnitTests\HPOSToggleTrait;
/**
* Tests for the WC_User class.
*/
class WC_User_Functions_Tests extends WC_Unit_Test_Case {
use HPOSToggleTrait;
/**
* Setup COT.
*/
public function setUp(): void {
parent::setUp();
$this->setup_cot();
$this->toggle_cot( false );
}
/**
* Clean COT specific things.
*/
public function tearDown(): void {
parent::tearDown();
$this->clean_up_cot_setup();
}
/**
* Test wc_get_customer_order_count. Borrowed from `WC_Tests_Customer_Functions` class for COT.
*/
public function test_hpos_wc_customer_bought_product() {
$this->toggle_cot( true );
$customer_id_1 = wc_create_new_customer( 'test@example.com', 'testuser', 'testpassword' );
$customer_id_2 = wc_create_new_customer( 'test2@example.com', 'testuser2', 'testpassword2' );
$product_1 = new WC_Product_Simple();
$product_1->save();
$product_id_1 = $product_1->get_id();
$product_2 = new WC_Product_Simple();
$product_2->save();
$product_id_2 = $product_2->get_id();
$order_1 = WC_Helper_Order::create_order( $customer_id_1, $product_1 );
$order_1->set_billing_email( 'test@example.com' );
$order_1->set_status( 'completed' );
$order_1->save();
$order_2 = WC_Helper_Order::create_order( $customer_id_2, $product_2 );
$order_2->set_billing_email( 'test2@example.com' );
$order_2->set_status( 'completed' );
$order_2->save();
$order_3 = WC_Helper_Order::create_order( $customer_id_1, $product_2 );
$order_3->set_billing_email( 'test@example.com' );
$order_3->set_status( 'pending' );
$order_3->save();
$this->assertTrue( wc_customer_bought_product( 'test@example.com', $customer_id_1, $product_id_1 ) );
$this->assertTrue( wc_customer_bought_product( '', $customer_id_1, $product_id_1 ) );
$this->assertTrue( wc_customer_bought_product( 'test@example.com', 0, $product_id_1 ) );
$this->assertFalse( wc_customer_bought_product( 'test@example.com', $customer_id_1, $product_id_2 ) );
$this->assertFalse( wc_customer_bought_product( 'test2@example.com', $customer_id_2, $product_id_1 ) );
}
}