Skip to content

Commit

Permalink
Improvement: Query optimisation for get_all_customer_currencies method (
Browse files Browse the repository at this point in the history
  • Loading branch information
ovidiul authored Sep 12, 2023
1 parent b0c0e79 commit ed190bc
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 15 deletions.
4 changes: 4 additions & 0 deletions changelog/6852-get_all_customer_currencies_improvement
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: update

Improved `get_all_customer_currencies` method to retrieve existing order currencies faster.
57 changes: 43 additions & 14 deletions includes/multi-currency/MultiCurrency.php
Original file line number Diff line number Diff line change
Expand Up @@ -1445,28 +1445,57 @@ public function is_multi_currency_settings_page(): bool {
);
}

/**
* Function used to compute the customer used currencies, used as internal callable for get_all_customer_currencies function.
*
* @return array
*/
public function callable_get_customer_currencies() {
global $wpdb;

$currencies = $this->get_available_currencies();
$query_union = [];

if ( class_exists( 'Automattic\WooCommerce\Utilities\OrderUtil' ) &&
\Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled() ) {
foreach ( $currencies as $currency ) {
$query_union[] = $wpdb->prepare(
"SELECT %s AS currency_code, EXISTS(SELECT currency FROM {$wpdb->prefix}wc_orders WHERE currency=%s LIMIT 1) AS exists_in_orders",
$currency->code,
$currency->code
);
}
} else {
foreach ( $currencies as $currency ) {
$query_union[] = $wpdb->prepare(
"SELECT %s AS currency_code, EXISTS(SELECT meta_value FROM {$wpdb->postmeta} WHERE meta_key=%s AND meta_value=%s LIMIT 1) AS exists_in_orders",
$currency->code,
'_order_currency',
$currency->code
);
}
}

$sub_query = join( ' UNION ALL ', $query_union );
$query = "SELECT currency_code FROM ( $sub_query ) as subquery WHERE subquery.exists_in_orders=1 ORDER BY currency_code ASC";
$currencies = $wpdb->get_col( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared

return [
'currencies' => $currencies,
'updated' => time(),
];
}

/**
* Get all the currencies that have been used in the store.
*
* @return array
*/
public function get_all_customer_currencies(): array {

$data = $this->database_cache->get_or_add(
Database_Cache::CUSTOMER_CURRENCIES_KEY,
function() {
global $wpdb;
if ( class_exists( 'Automattic\WooCommerce\Utilities\OrderUtil' ) &&
\Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled() ) {
$currencies = $wpdb->get_col( "SELECT DISTINCT(currency) FROM {$wpdb->prefix}wc_orders" );
} else {
$currencies = $wpdb->get_col( "SELECT DISTINCT(meta_value) FROM {$wpdb->postmeta} WHERE meta_key = '_order_currency'" );
}

return [
'currencies' => $currencies,
'updated' => time(),
];
},
[ $this, 'callable_get_customer_currencies' ],
function ( $data ) {
// Return true if the data looks valid and was updated an hour or less ago.
return is_array( $data ) &&
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/multi-currency/test-class-multi-currency.php
Original file line number Diff line number Diff line change
Expand Up @@ -978,7 +978,7 @@ function( $key, $generator, $validator ) {

$result = $this->multi_currency->get_all_customer_currencies();

$this->assertEquals( [ 'GBP', 'EUR', 'USD' ], $result );
$this->assertEquals( [ 'EUR', 'GBP', 'USD' ], $result );

foreach ( $mock_orders as $order_id ) {
wp_delete_post( $order_id, true );
Expand Down

0 comments on commit ed190bc

Please sign in to comment.