ORdersTableDataStore: capture+log exceptions when populating order properties.

This makes the behavior of wc_get_order to be the same as when HPOS
is disabled (and Abstract_WC_Order_Data_Store_CPT is thus used
instead): the order is still retrieved (although without the errored
properties set) instead of the function just returning false.

An example of when this can happen is if an order refund has the id
of a no longer existing order as the parent id.
This commit is contained in:
Nestor Soriano 2023-06-21 10:25:14 +02:00
parent 5b0aa22402
commit 12a453f1a5
No known key found for this signature in database
GPG Key ID: 08110F3518C12CAD
2 changed files with 90 additions and 4 deletions

View File

@ -1346,11 +1346,31 @@ WHERE
continue;
}
if ( 'date' === $prop_details['type'] ) {
$prop_value = $this->string_to_timestamp( $prop_value );
}
try {
if ( 'date' === $prop_details['type'] ) {
$prop_value = $this->string_to_timestamp( $prop_value );
}
$this->set_order_prop( $order, $prop_details['name'], $prop_value );
$this->set_order_prop( $order, $prop_details['name'], $prop_value );
} catch ( \Exception $e ) {
$order_id = $order->get_id();
$this->error_logger->warning(
sprintf(
/* translators: %1$d = peoperty name, %2$d = order ID, %3$s = error message. */
__( 'Error when setting property \'%1$s\' for order %2$d: %3$s', 'woocommerce' ),
$prop_details['name'],
$order_id,
$e->getMessage()
),
array(
'exception_code' => $e->getCode(),
'exception_msg' => $e->getMessage(),
'origin' => __METHOD__,
'order_id' => $order_id,
'property_name' => $prop_details['name'],
)
);
}
}
}
}

View File

@ -2146,4 +2146,70 @@ class OrdersTableDataStoreTests extends WC_Unit_Test_Case {
$this->assertEquals( 'wc-completed', $db_row['data']['status'] );
}
/**
* @testDox An exception thrown while populating the properties of an order is captured and logged as a warning.
*/
public function test_error_when_setting_order_property_is_captured_and_logged() {
global $wpdb;
$this->toggle_cot( true );
$this->disable_cot_sync();
// phpcs:disable Squiz.Commenting
$fake_logger = new class() {
public $warnings = array();
public function warning( $message, $data ) {
$this->warnings[] = array(
'message' => $message,
'data' => $data,
);
}
};
// phpcs:enable Squiz.Commenting
$this->register_legacy_proxy_function_mocks(
array(
'wc_get_logger' => function() use ( $fake_logger ) {
return $fake_logger;
},
)
);
$order = new WC_Order();
$order->save();
$product_id = $order->add_product( WC_Helper_Product::create_simple_product(), 1 );
$order->calculate_totals();
$order->save();
$refund = wc_create_refund(
array(
'order_id' => $order->get_id(),
'line_items' => array(
$product_id => array(
'id' => $product_id,
'qty' => 1,
'refund_total' => 1,
),
),
)
);
$refund->save();
$this->assertEquals( $order->get_id(), $refund->get_parent_id() );
$wpdb->update(
$this->sut::get_orders_table_name(),
array( 'parent_order_id' => 999999 ),
array( 'id' => $refund->get_id() ),
array( 'parent_order_id' => '%d' ),
array( 'id' => '%d' ),
);
$refund = wc_get_order( $refund->get_id() );
$this->assertEquals( 0, $refund->get_parent_id() );
$this->assertEquals( "Error when setting property 'parent_id' for order {$refund->get_id()}: Invalid parent ID", current( $fake_logger->warnings )['message'] );
}
}