Upgrade misc WooCommerce bits to support COT (#34124)

Update miscellanous WC bits to support custom tables.

* Add changelog.
* Add test for order_meta call.
* Make CI happy.
* Add tests for before_delete_order.
* Add test for is_valid_resource
* Add tests for PayPal API.
* Add test for save paypal meta data.
* Minor fixup.
This commit is contained in:
Vedanshu Jain 2022-08-03 22:11:37 +05:30 committed by GitHub
parent 397a7846b5
commit e4dae58502
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 226 additions and 18 deletions

View File

@ -0,0 +1,4 @@
Significance: patch
Type: update
Update misc WC code to support COT>

View File

@ -502,7 +502,7 @@ class WC_Emails {
$fields[ $key ] = array(
'label' => wptexturize( $key ),
'value' => wptexturize( get_post_meta( $order->get_id(), $field, true ) ),
'value' => wptexturize( $order->get_meta( $field ) ),
);
}
}

View File

@ -194,7 +194,7 @@ class WC_Order_Refund extends WC_Abstract_Order {
return false;
}
$result = get_post( $id );
$result = wc_get_order( $id );
if ( $result ) {
$this->populate( $result );

View File

@ -11,6 +11,7 @@
use Automattic\WooCommerce\Internal\DataStores\Orders\DataSynchronizer;
use Automattic\WooCommerce\Internal\ProductAttributesLookup\LookupDataStore as ProductAttributesLookupDataStore;
use Automattic\WooCommerce\Proxies\LegacyProxy;
use Automattic\WooCommerce\Utilities\OrderUtil;
defined( 'ABSPATH' ) || exit;
@ -427,7 +428,7 @@ class WC_Post_Data {
* @param int $order_id Order ID.
*/
public static function before_delete_order( $order_id ) {
if ( in_array( get_post_type( $order_id ), wc_get_order_types(), true ) ) {
if ( OrderUtil::is_order( $order_id, wc_get_order_types() ) ) {
// Clean up user.
$order = wc_get_order( $order_id );
@ -463,7 +464,7 @@ class WC_Post_Data {
public static function delete_order_items( $postid ) {
global $wpdb;
if ( in_array( get_post_type( $postid ), wc_get_order_types(), true ) ) {
if ( OrderUtil::is_order( $postid, wc_get_order_types() ) ) {
do_action( 'woocommerce_delete_order_items', $postid );
$wpdb->query(
@ -485,7 +486,7 @@ class WC_Post_Data {
* @param int $postid Post ID.
*/
public static function delete_order_downloadable_permissions( $postid ) {
if ( in_array( get_post_type( $postid ), wc_get_order_types(), true ) ) {
if ( OrderUtil::is_order( $postid, wc_get_order_types() ) ) {
do_action( 'woocommerce_delete_order_downloadable_permissions', $postid );
$data_store = WC_Data_Store::load( 'customer-download' );

View File

@ -13,6 +13,7 @@
use Automattic\Jetpack\Constants;
use Automattic\WooCommerce\Utilities\NumberUtil;
use Automattic\WooCommerce\Utilities\OrderUtil;
defined( 'ABSPATH' ) || exit;
@ -287,7 +288,7 @@ class WC_Webhook extends WC_Legacy_Webhook {
}
// Check registered order types for order types args.
if ( 'order' === $resource && ! in_array( get_post_type( absint( $arg ) ), wc_get_order_types( 'order-webhooks' ), true ) ) {
if ( 'order' === $resource && ! OrderUtil::is_order( absint( $arg ), wc_get_order_types( 'order-webhooks' ) ) ) {
return false;
}
}

View File

@ -428,8 +428,9 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
case 'Completed':
/* translators: 1: Amount, 2: Authorization ID, 3: Transaction ID */
$order->add_order_note( sprintf( __( 'Payment of %1$s was captured - Auth ID: %2$s, Transaction ID: %3$s', 'woocommerce' ), $result->AMT, $result->AUTHORIZATIONID, $result->TRANSACTIONID ) );
update_post_meta( $order->get_id(), '_paypal_status', $result->PAYMENTSTATUS );
update_post_meta( $order->get_id(), '_transaction_id', $result->TRANSACTIONID );
$order->update_meta_data( '_paypal_status', $result->PAYMENTSTATUS );
$order->set_transaction_id( $result->TRANSACTIONID );
$order->save();
break;
default:
/* translators: 1: Authorization ID, 2: Payment status */

View File

@ -345,14 +345,15 @@ class WC_Gateway_Paypal_IPN_Handler extends WC_Gateway_Paypal_Response {
*/
protected function save_paypal_meta_data( $order, $posted ) {
if ( ! empty( $posted['payment_type'] ) ) {
update_post_meta( $order->get_id(), 'Payment type', wc_clean( $posted['payment_type'] ) );
$order->update_meta_data( 'Payment type', wc_clean( $posted['payment_type'] ) );
}
if ( ! empty( $posted['txn_id'] ) ) {
update_post_meta( $order->get_id(), '_transaction_id', wc_clean( $posted['txn_id'] ) );
$order->set_transaction_id( wc_clean( $posted['txn_id'] ) );
}
if ( ! empty( $posted['payment_status'] ) ) {
update_post_meta( $order->get_id(), '_paypal_status', wc_clean( $posted['payment_status'] ) );
$order->update_meta_data( '_paypal_status', wc_clean( $posted['payment_status'] ) );
}
$order->save();
}
/**

View File

@ -5,6 +5,8 @@
* @package WooCommerce\Tracks
*/
use Automattic\WooCommerce\Utilities\OrderUtil;
defined( 'ABSPATH' ) || exit;
/**
@ -92,9 +94,7 @@ class WC_Orders_Tracking {
* @param int $id Order id.
*/
public function track_created_date_change( $id ) {
$post_type = get_post_type( $id );
if ( 'shop_order' !== $post_type ) {
if ( ! OrderUtil::is_order( $id ) ) {
return;
}
@ -168,7 +168,7 @@ class WC_Orders_Tracking {
isset( $referring_args['action'] ) &&
'edit' === $referring_args['action'] &&
isset( $referring_args['post'] ) &&
'shop_order' === get_post_type( $referring_args['post'] )
'shop_order' === OrderUtil::get_order_type( $referring_args['post'] )
) {
WC_Tracks::record_event( 'order_edit_add_order' );
}

View File

@ -638,7 +638,7 @@ function wc_create_refund( $args = array() ) {
} catch ( Exception $e ) {
if ( isset( $refund ) && is_a( $refund, 'WC_Order_Refund' ) ) {
wp_delete_post( $refund->get_id(), true );
$refund->delete( true );
}
return new WP_Error( 'error', $e->getMessage() );
}

View File

@ -260,7 +260,7 @@ function wc_update_new_customer_past_orders( $customer_id ) {
do_action( 'woocommerce_update_new_customer_past_order', $order_id, $customer );
if ( get_post_status( $order_id ) === 'wc-completed' ) {
if ( $order->get_status() === 'wc-completed' ) {
$complete++;
}

View File

@ -89,7 +89,9 @@ class COTMigrationUtil {
* @return int Order or post ID.
*/
public function get_post_or_order_id( $post_or_order_object ) : int {
if ( $post_or_order_object instanceof WC_Order ) {
if ( is_int( $post_or_order_object ) ) {
return $post_or_order_object;
} elseif ( $post_or_order_object instanceof WC_Order ) {
return $post_or_order_object->get_id();
} elseif ( $post_or_order_object instanceof WP_Post ) {
return $post_or_order_object->ID;
@ -97,4 +99,30 @@ class COTMigrationUtil {
return 0;
}
/**
* Checks if passed id, post or order object is a WC_Order object.
*
* @param int|WP_Post|WC_Order $order_id Order ID, post object or order object.
* @param string[] $types Types to match against.
*
* @return bool Whether the passed param is an order.
*/
public function is_order( $order_id, array $types = array( 'shop_order' ) ) : bool {
$order_id = $this->get_post_or_order_id( $order_id );
$order_data_store = \WC_Data_Store::load( 'order' );
return in_array( $order_data_store->get_order_type( $order_id ), $types, true );
}
/**
* Returns type pf passed id, post or order object.
*
* @param int|WP_Post|WC_Order $order_id Order ID, post object or order object.
*
* @return string|null Type of the order.
*/
public function get_order_type( $order_id ) : ?string {
$order_id = $this->get_post_or_order_id( $order_id );
$order_data_store = \WC_Data_Store::load( 'order' );
return $order_data_store->get_order_type( $order_id );
}
}

View File

@ -70,4 +70,27 @@ final class OrderUtil {
public static function get_post_or_order_id( $post_or_order_object ) : int {
return wc_get_container()->get( COTMigrationUtil::class )->get_post_or_order_id( $post_or_order_object );
}
/**
* Checks if passed id, post or order object is a WC_Order object.
*
* @param int|WP_Post|WC_Order $order_id Order ID, post object or order object.
* @param string[] $types Types to match against.
*
* @return bool Whether the passed param is an order.
*/
public static function is_order( $order_id, $types = array( 'shop_order' ) ) {
return wc_get_container()->get( COTMigrationUtil::class )->is_order( $order_id, $types );
}
/**
* Returns type pf passed id, post or order object.
*
* @param int|WP_Post|WC_Order $order_id Order ID, post object or order object.
*
* @return string|null Type of the order.
*/
public static function get_order_type( $order_id ) {
return wc_get_container()->get( COTMigrationUtil::class )->get_order_type( $order_id );
}
}

View File

@ -14,6 +14,7 @@ class WC_Emails_Tests extends \WC_Unit_Test_Case {
// 10 is expected priority of the hook.
$this->assertEquals( 10, has_action( 'woocommerce_email_header', array( $email_object, 'email_header' ) ) );
ob_start();
// phpcs:ignore WooCommerce.Commenting.CommentHooks.MissingHookComment
do_action( 'woocommerce_email_header', 'header' );
$content = ob_get_contents();
ob_end_clean();
@ -29,9 +30,33 @@ class WC_Emails_Tests extends \WC_Unit_Test_Case {
// 10 is expected priority of the hook.
$this->assertEquals( 10, has_action( 'woocommerce_email_footer', array( $email_object, 'email_footer' ) ) );
ob_start();
// phpcs:ignore WooCommerce.Commenting.CommentHooks.MissingHookComment
do_action( 'woocommerce_email_footer' );
$content = ob_get_contents();
ob_end_clean();
$this->assertFalse( empty( $content ) );
}
/**
* Test that order meta function outputs linked meta.
*/
public function test_order_meta() {
add_filter(
'woocommerce_email_order_meta_keys',
function () {
return array( 'dummy_key' );
}
);
$order = \Automattic\WooCommerce\RestApi\UnitTests\Helpers\OrderHelper::create_order();
$order->add_meta_data( 'dummy_key', 'dummy_meta_value' );
$order->save();
$email_object = new WC_Emails();
ob_start();
$email_object->order_meta( $order, true, true );
$content = ob_get_contents();
ob_end_clean();
$this->assertContains( 'dummy_key', $content );
$this->assertContains( 'dummy_meta_value', $content );
}
}

View File

@ -32,4 +32,17 @@ class WC_Post_Data_Test extends \WC_Unit_Test_Case {
$this->assertEquals( 'c&c', $post_data->post_title );
$coupon->delete( true );
}
/**
* Order items should be deleted before deleting order.
*/
public function test_before_delete_order() {
$order = \Automattic\WooCommerce\RestApi\UnitTests\Helpers\OrderHelper::create_order();
$items = $order->get_items();
$this->assertNotEmpty( $items );
WC_Post_Data::before_delete_order( $order->get_id() );
$order = wc_get_order( $order->get_id() );
$this->assertEmpty( $order->get_items() );
}
}

View File

@ -0,0 +1,37 @@
<?php
/**
* Tests for WC_Webhook class.
*/
/**
* Tests for WC_Webhook class.
*/
class WC_Webhook_Test extends WC_Unit_Test_Case {
/**
* @testDox Check if valid resource is true when both arg and topic are valid.
*/
public function test_is_valid_resource() {
$webhook = new WC_Webhook();
$webhook->set_topic( 'order.created' );
$order = \Automattic\WooCommerce\RestApi\UnitTests\Helpers\OrderHelper::create_order();
$call_is_valid_function = function ( $arg ) {
return $this->is_valid_resource( $arg );
};
$this->assertTrue( $call_is_valid_function->call( $webhook, $order->get_id() ) );
}
/**
* @testDox Check if valid resource is false when both arg and topic are different.
*/
public function test_is_valid_resource_false() {
$webhook = new WC_Webhook();
$webhook->set_topic( 'order.created' );
$product = \Automattic\WooCommerce\RestApi\UnitTests\Helpers\ProductHelper::create_simple_product();
$call_is_valid_function = function ( $arg ) {
return $this->is_valid_resource( $arg );
};
$this->assertFalse( $call_is_valid_function->call( $webhook, $product->get_id() ) );
}
}

View File

@ -95,4 +95,78 @@ class WC_Gateway_Paypal_Test extends \WC_Unit_Test_Case {
return $value;
}
/**
* Test do_capture when API returns success.
*/
public function test_capture_payment() {
$order = WC_Helper_Order::create_order();
$order->update_meta_data( '_paypal_status', 'pending' );
$order->set_transaction_id( $this->transaction_id_26960 );
$order->set_payment_method( 'paypal' );
$order->save();
// Force HTTP error.
add_filter( 'pre_http_request', array( $this, '__return_paypal_success' ), 10, 2 );
( new WC_Gateway_Paypal() )->capture_payment( $order->get_id() );
remove_filter( 'pre_http_request', array( $this, '__return_paypal_success' ) );
$order = wc_get_order( $order->get_id() );
$this->assertEquals( 'Completed', $order->get_meta( '_paypal_status' ) );
}
/**
* Helper function for raising success when this is a PayPal request using transaction_id_26960.
*
* @param bool $value Original pre-value, likely to be false.
* @param array $parsed_url Parsed URL object.
*
* @return bool|WP_Error Return success object or return original value.
*/
public function __return_paypal_success( $value, $parsed_url ) {
$response_body = array(
'TRANSACTIONID' => $this->transaction_id_26960,
'PAYMENTSTATUS' => 'Completed',
'AMT' => '100.00',
'CURRENCYCODE' => 'USD',
'AVSCODE' => 'X',
'CVV2MATCH' => 'M',
'ACK' => 'Success',
'AUTHORIZATIONID' => $this->transaction_id_26960,
);
$response = array( 'body' => http_build_query( $response_body ) );
if ( isset( $parsed_url['body'] ) && isset( $parsed_url['body']['AUTHORIZATIONID'] ) && $this->transaction_id_26960 === $parsed_url['body']['AUTHORIZATIONID'] ) {
return $response;
}
if ( isset( $parsed_url['body'] ) && isset( $parsed_url['body']['TRANSACTIONID'] ) && $this->transaction_id_26960 === $parsed_url['body']['TRANSACTIONID'] ) {
return $response;
}
return $value;
}
/**
* Test that paypal metadata is saved properly in opn request.
*/
public function test_ipn_save_paypal_meta_data() {
$order = WC_Helper_Order::create_order();
$order->save();
$posted_meta = array(
'payment_type' => 'paypal',
'txn_id' => $this->transaction_id_26960,
'payment_status' => 'Completed',
);
$call_posted_meta = function ( $order, $posted_meta ) {
$this->save_paypal_meta_data( $order, $posted_meta );
};
$call_posted_meta->call( ( new WC_Gateway_Paypal_IPN_Handler( true ) ), $order, $posted_meta );
$this->assertEquals( $order->get_meta( 'Payment type' ), 'paypal' );
$this->assertEquals( $order->get_transaction_id(), $this->transaction_id_26960 );
$this->assertEquals( $order->get_meta( '_paypal_status' ), 'Completed' );
}
}