Add WC Tracker unique payment method (#37951)

Co-authored-by: Corey McKrill <916023+coreymckrill@users.noreply.github.com>
This commit is contained in:
Menaka S 2023-05-10 11:22:58 +04:00 committed by GitHub
parent 1b8eeed2e2
commit c3d06ad05f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 147 additions and 12 deletions

View File

@ -0,0 +1,4 @@
Significance: minor
Type: update
In the WC Tracker, group payment methods and origins ignoring unique ids within their names.

View File

@ -419,7 +419,7 @@ class WC_Tracker {
SUM( order_meta.meta_value ) AS 'gross_total'
FROM {$wpdb->prefix}posts AS orders
LEFT JOIN {$wpdb->prefix}postmeta AS order_meta ON order_meta.post_id = orders.ID
WHERE order_meta.meta_key = '_order_total'
WHERE order_meta.meta_key = '_order_total'
AND orders.post_status in ( 'wc-completed', 'wc-refunded' )
GROUP BY order_meta.meta_key
"
@ -435,7 +435,7 @@ class WC_Tracker {
SUM( order_meta.meta_value ) AS 'gross_total'
FROM {$wpdb->prefix}posts AS orders
LEFT JOIN {$wpdb->prefix}postmeta AS order_meta ON order_meta.post_id = orders.ID
WHERE order_meta.meta_key = '_order_total'
WHERE order_meta.meta_key = '_order_total'
AND orders.post_status = 'wc-processing'
GROUP BY order_meta.meta_key
"
@ -498,6 +498,69 @@ class WC_Tracker {
return array_merge( $min_max, $processing_min_max );
}
/**
* Extract the group key for an associative array of objects which have unique ids in the key.
* A 'group_key' property is introduced in the object.
* For example, two objects with keys like 'WooDataPay ** #123' and 'WooDataPay ** #78' would
* both have a group_key of 'WooDataPay **' after this function call.
*
* @param array $objects The array of objects that need to be grouped.
* @param string $default_key The property that will be the default group_key.
* @return array Contains the objects with a group_key property.
*/
private static function extract_group_key( $objects, $default_key ) {
$keys = array_keys( $objects );
// Sort keys by length and then by characters within the same length keys.
usort(
$keys,
function( $a, $b ) {
if ( strlen( $a ) === strlen( $b ) ) {
return strcmp( $a, $b );
}
return ( strlen( $a ) < strlen( $b ) ) ? -1 : 1;
}
);
// Look for common tokens in every pair of adjacent keys.
$prev = '';
foreach ( $keys as $key ) {
if ( $prev ) {
$comm_tokens = array();
// Tokenize the current and previous gateway names.
$curr_tokens = preg_split( '/[ :,\-_]+/', $key );
$prev_tokens = preg_split( '/[ :,\-_]+/', $prev );
$len_curr = count( $curr_tokens );
$len_prev = count( $prev_tokens );
$index_unique = -1;
// Gather the common tokens.
// Let us allow for the unique reference id to be anywhere in the name.
for ( $i = 0; $i < $len_curr && $i < $len_prev; $i++ ) {
if ( $curr_tokens[ $i ] === $prev_tokens[ $i ] ) {
$comm_tokens[] = $curr_tokens[ $i ];
} elseif ( preg_match( '/\d/', $curr_tokens[ $i ] ) && preg_match( '/\d/', $prev_tokens[ $i ] ) ) {
$index_unique = $i;
}
}
// If only one token is different, and those tokens contain digits, then that could be the unique id.
if ( count( $curr_tokens ) - count( $comm_tokens ) <= 1 && count( $comm_tokens ) > 0 && $index_unique > -1 ) {
$objects[ $key ]->group_key = implode( ' ', $comm_tokens );
$objects[ $prev ]->group_key = implode( ' ', $comm_tokens );
} else {
$objects[ $key ]->group_key = $objects[ $key ]->$default_key;
}
} else {
$objects[ $key ]->group_key = $objects[ $key ]->$default_key;
}
$prev = $key;
}
return $objects;
}
/**
* Get order details by gateway.
*
@ -506,7 +569,7 @@ class WC_Tracker {
private static function get_orders_by_gateway() {
global $wpdb;
$orders_by_gateway = $wpdb->get_results(
$orders_and_gateway_details = $wpdb->get_results(
"
SELECT
gateway, currency, SUM(total) AS totals, COUNT(order_id) AS counts
@ -530,14 +593,56 @@ class WC_Tracker {
);
$orders_by_gateway_currency = array();
foreach ( $orders_by_gateway as $orders_details ) {
$gateway = 'gateway_' . $orders_details->gateway;
$currency = $orders_details->currency;
$count = $gateway . '_' . $currency . '_count';
$total = $gateway . '_' . $currency . '_total';
$orders_by_gateway_currency[ $count ] = $orders_details->counts;
$orders_by_gateway_currency[ $total ] = $orders_details->totals;
// The associative array that is created as the result of array_reduce is passed to extract_group_key()
// This function has the logic that will remove specific transaction identifiers that may sometimes be part of a
// payment method. For example, two payments methods like 'WooDataPay ** #123' and 'WooDataPay ** #78' would
// both have the same group_key 'WooDataPay **'.
$orders_by_gateway = self::extract_group_key(
// Convert into an associative array with a combination of currency and gateway as key.
array_reduce(
$orders_and_gateway_details,
function( $result, $item ) {
$item->gateway = preg_replace( '/\s+/', ' ', $item->gateway );
// Introduce currency as a prefix for the key.
$key = $item->currency . '==' . $item->gateway;
$result[ $key ] = $item;
return $result;
},
array()
),
'gateway'
);
// Aggregate using group_key.
foreach ( $orders_by_gateway as $orders_details ) {
$gkey = $orders_details->group_key;
// Remove currency as prefix of key for backward compatibility.
if ( str_contains( $gkey, '==' ) ) {
$tokens = preg_split( '/==/', $gkey );
$key = $tokens[1];
} else {
$key = $gkey;
}
$key = str_replace( array( 'payment method', 'payment gateway', 'gateway' ), '', strtolower( $key ) );
$key = trim( preg_replace( '/[: ,#*\-_]+/', ' ', $key ) );
// Add currency as postfix of gateway for backward compatibility.
$key = 'gateway_' . $key . '_' . $orders_details->currency;
$count_key = $key . '_count';
$total_key = $key . '_total';
if ( array_key_exists( $count_key, $orders_by_gateway_currency ) || array_key_exists( $total_key, $orders_by_gateway_currency ) ) {
$orders_by_gateway_currency[ $count_key ] = $orders_by_gateway_currency[ $count_key ] + $orders_details->counts;
$orders_by_gateway_currency[ $total_key ] = $orders_by_gateway_currency[ $total_key ] + $orders_details->totals;
} else {
$orders_by_gateway_currency[ $count_key ] = $orders_details->counts;
$orders_by_gateway_currency[ $total_key ] = $orders_details->totals;
}
}
return $orders_by_gateway_currency;
@ -566,9 +671,35 @@ class WC_Tracker {
"
);
// The associative array that is created as the result of array_reduce is passed to extract_group_key()
// This function has the logic that will remove specific identifiers that may sometimes be part of an origin.
// For example, two origins like 'Import #123' and 'Import ** #78' would both have a group_key 'Import **'.
$orders_and_origins = self::extract_group_key(
// Convert into an associative array with the origin as key.
array_reduce(
$orders_origin,
function( $result, $item ) {
$key = $item->origin;
$result[ $key ] = $item;
return $result;
},
array()
),
'origin'
);
$orders_by_origin = array();
foreach ( $orders_origin as $origin ) {
$orders_by_origin[ $origin->origin ] = (int) $origin->count;
// Aggregate using group_key.
foreach ( $orders_and_origins as $origin ) {
$key = strtolower( $origin->group_key );
if ( array_key_exists( $key, $orders_by_origin ) ) {
$orders_by_origin[ $key ] = $orders_by_origin[ $key ] + (int) $origin->count;
} else {
$orders_by_origin[ $key ] = (int) $origin->count;
}
}
return array( 'created_via' => $orders_by_origin );