Merge pull request #13044 from woocommerce/crud-perf-tweaks

[2.7] CRUD performance improvements for emails
This commit is contained in:
Claudio Sanches 2017-02-09 13:25:29 -02:00 committed by GitHub
commit e3b563c518
26 changed files with 235 additions and 140 deletions

View File

@ -578,7 +578,7 @@ abstract class WC_Data {
protected function get_prop( $prop, $context = 'view' ) {
$value = null;
if ( array_key_exists( $prop, $this->data ) ) {
if ( isset( $this->data[ $prop ] ) ) {
$value = isset( $this->changes[ $prop ] ) ? $this->changes[ $prop ] : $this->data[ $prop ];
if ( 'view' === $context ) {

View File

@ -51,13 +51,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
* @since 2.7.0
* @var array
*/
protected $items = array(
'line_items' => null,
'coupon_lines' => null,
'shipping_lines' => null,
'fee_lines' => null,
'tax_lines' => null,
);
protected $items = array();
/**
* Order items that need deleting are stored here.
@ -197,7 +191,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
}
$this->items_to_delete = array();
// Add/save items
// Add/save items.
foreach ( $this->items as $item_group => $items ) {
if ( is_array( $items ) ) {
foreach ( $items as $item_key => $item ) {
@ -652,6 +646,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
/**
* Remove all line items (products, coupons, shipping, taxes) from the order.
*
* @param string $type Order item type. Default null.
*/
public function remove_order_items( $type = null ) {
@ -659,22 +654,17 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
$this->data_store->delete_items( $this, $type );
if ( $group = $this->type_to_group( $type ) ) {
$this->items[ $group ] = null;
unset( $this->items[ $group ] );
}
} else {
$this->data_store->delete_items( $this );
$this->items = array(
'line_items' => null,
'coupon_lines' => null,
'shipping_lines' => null,
'fee_lines' => null,
'tax_lines' => null,
);
$this->items = array();
}
}
/**
* Convert a type to a types group.
*
* @param string $type
* @return string group
*/
@ -691,6 +681,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
/**
* Return an array of items/products within this order.
*
* @param string|array $types Types of line items to get (array or string).
* @return Array of WC_Order_item
*/
@ -700,7 +691,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
foreach ( $types as $type ) {
if ( $group = $this->type_to_group( $type ) ) {
if ( is_null( $this->items[ $group ] ) ) {
if ( ! isset( $this->items[ $group ] ) ) {
$this->items[ $group ] = $this->data_store->read_items( $this, $type );
}
// Don't use array_merge here because keys are numeric
@ -713,6 +704,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
/**
* Return an array of fees within this order.
*
* @return array
*/
public function get_fees() {
@ -721,6 +713,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
/**
* Return an array of taxes within this order.
*
* @return array
*/
public function get_taxes() {
@ -729,6 +722,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
/**
* Return an array of shipping costs within this order.
*
* @return array
*/
public function get_shipping_methods() {
@ -737,6 +731,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
/**
* Gets formatted shipping method title.
*
* @return string
*/
public function get_shipping_method() {
@ -749,6 +744,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
/**
* Get coupon codes only.
*
* @return array
*/
public function get_used_coupons() {
@ -780,6 +776,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
/**
* Get an order item object, based on it's type.
*
* @since 2.7.0
* @param int $item_id
* @return WC_Order_Item
@ -790,6 +787,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
/**
* Get key for where a certain item type is stored in _items.
*
* @since 2.7.0
* @param $item object Order item (product, shipping, fee, coupon, tax)
* @return string
@ -812,6 +810,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
/**
* Remove item from the order.
*
* @param int $item_id
*/
public function remove_item( $item_id ) {
@ -828,6 +827,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
/**
* Adds an order item to this order. The order item will not persist until save.
*
* @since 2.7.0
* @param WC_Order_Item Order item object (product, shipping, fee, coupon, tax)
*/
@ -837,7 +837,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
}
// Make sure existing items are loaded so we can append this new one.
if ( is_null( $this->items[ $items_key ] ) ) {
if ( ! isset( $this->items[ $items_key ] ) ) {
$this->items[ $items_key ] = $this->get_items( $item->get_type() );
}
@ -845,8 +845,8 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
$item->set_order_id( $this->get_id() );
// Append new row with generated temporary ID
if ( $item->get_id() ) {
$this->items[ $items_key ][ $item->get_id() ] = $item;
if ( $item_id = $item->get_id() ) {
$this->items[ $items_key ][ $item_id ] = $item;
} else {
$this->items[ $items_key ][ 'new:' . sizeof( $this->items[ $items_key ] ) ] = $item;
}
@ -855,6 +855,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
/**
* Add a product line item to the order. This is the only line item type with
* it's own method because it saves looking up order amounts (costs are added up for you).
*
* @param \WC_Product $product
* @param int $qty
* @param array $args

View File

@ -349,10 +349,6 @@ class WC_Checkout {
$item->legacy_cart_item_key = $cart_item_key; // @deprecated For legacy actions.
$item->set_props( array(
'quantity' => $values['quantity'],
'name' => $product ? $product->get_name() : '',
'tax_class' => $product ? $product->get_tax_class() : '',
'product_id' => $product ? ( $product->is_type( 'variation' ) ? $product->get_parent_id() : $product->get_id() ) : 0,
'variation_id' => $product && $product->is_type( 'variation' ) ? $product->get_id() : 0,
'variation' => $values['variation'],
'subtotal' => $values['line_subtotal'],
'total' => $values['line_total'],
@ -360,6 +356,14 @@ class WC_Checkout {
'total_tax' => $values['line_tax'],
'taxes' => $values['line_tax_data'],
) );
if ( $product ) {
$item->set_props( array(
'name' => $product->get_name(),
'tax_class' => $product->get_tax_class(),
'product_id' => $product->is_type( 'variation' ) ? $product->get_parent_id() : $product->get_id(),
'variation_id' => $product->is_type( 'variation' ) ? $product->get_id() : 0,
) );
}
$item->set_backorder_meta();
/**

View File

@ -84,17 +84,38 @@ class WC_Emails {
) );
foreach ( $email_actions as $action ) {
add_action( $action, array( __CLASS__, 'send_transactional_email' ), 10, 10 );
add_action( $action, array( __CLASS__, 'queue_transactional_email' ), 10, 10 );
}
}
/**
* Queue transactional email via cron so it's not sent in current request.
*/
public static function queue_transactional_email() {
wp_schedule_single_event( time() + 10, 'woocommerce_send_queued_transactional_email', array(
'filter' => current_filter(),
'args' => func_get_args(),
) );
}
/**
* Init the mailer instance and call the notifications for the current filter.
*
* @internal param array $args (default: array())
*/
public static function send_transactional_email() {
public static function send_queued_transactional_email( $filter = '', $args = array() ) {
self::instance(); // Init self so emails exist.
do_action_ref_array( $filter . '_notification', $args );
}
/**
* Init the mailer instance and call the notifications for the current filter.
*
* @internal param array $args (default: array())
*/
public static function send_transactional_email( $args = array() ) {
$args = func_get_args();
self::instance();
self::instance(); // Init self so emails exist.
do_action_ref_array( current_filter() . '_notification', $args );
}

View File

@ -44,7 +44,15 @@ class WC_Order_Factory {
}
try {
return new $classname( $order_id );
// Try to get from cache, otherwise create a new object,
$order = wp_cache_get( 'order-' . $order_id, 'orders' );
if ( ! is_a( $order, 'WC_Order' ) ) {
$order = new $classname( $order_id );
wp_cache_set( 'order-' . $order_id, $order, 'orders' );
}
return $order;
} catch ( Exception $e ) {
return false;
}
@ -95,7 +103,15 @@ class WC_Order_Factory {
}
if ( $classname ) {
try {
return new $classname( $id );
// Try to get from cache, otherwise create a new object,
$item = wp_cache_get( 'order-item-' . $id, 'order-items' );
if ( ! is_a( $item, 'WC_Order_Item' ) ) {
$item = new $classname( $id );
wp_cache_set( 'order-item-' . $id, $item, 'order-items' );
}
return $item;
} catch ( Exception $e ) {
return false;
}

View File

@ -196,8 +196,9 @@ class WC_Order_Item_Product extends WC_Order_Item {
* Set meta data for backordered products.
*/
public function set_backorder_meta() {
if ( $this->get_product()->backorders_require_notification() && $this->get_product()->is_on_backorder( $this->get_quantity() ) ) {
$this->add_meta_data( apply_filters( 'woocommerce_backordered_item_meta_name', __( 'Backordered', 'woocommerce' ) ), $this->get_quantity() - max( 0, $this->get_product()->get_stock_quantity() ), true );
$product = $this->get_product();
if ( $product && $product->backorders_require_notification() && $product->is_on_backorder( $this->get_quantity() ) ) {
$this->add_meta_data( apply_filters( 'woocommerce_backordered_item_meta_name', __( 'Backordered', 'woocommerce' ) ), $this->get_quantity() - max( 0, $product->get_stock_quantity() ), true );
}
}

View File

@ -287,14 +287,14 @@ class WC_Order extends WC_Abstract_Order {
*/
protected function status_transition() {
if ( $this->status_transition ) {
do_action( 'woocommerce_order_status_' . $this->status_transition['to'], $this->get_id() );
do_action( 'woocommerce_order_status_' . $this->status_transition['to'], $this->get_id(), $this );
if ( ! empty( $this->status_transition['from'] ) ) {
/* translators: 1: old order status 2: new order status */
$transition_note = sprintf( __( 'Order status changed from %1$s to %2$s.', 'woocommerce' ), wc_get_order_status_name( $this->status_transition['from'] ), wc_get_order_status_name( $this->status_transition['to'] ) );
do_action( 'woocommerce_order_status_' . $this->status_transition['from'] . '_to_' . $this->status_transition['to'], $this->get_id() );
do_action( 'woocommerce_order_status_changed', $this->get_id(), $this->status_transition['from'], $this->status_transition['to'] );
do_action( 'woocommerce_order_status_' . $this->status_transition['from'] . '_to_' . $this->status_transition['to'], $this->get_id(), $this );
do_action( 'woocommerce_order_status_changed', $this->get_id(), $this->status_transition['from'], $this->status_transition['to'], $this );
} else {
/* translators: %s: new order status */
$transition_note = sprintf( __( 'Order status set to %s.', 'woocommerce' ), wc_get_order_status_name( $this->status_transition['to'] ) );

View File

@ -242,6 +242,7 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
protected function clear_caches( &$order ) {
clean_post_cache( $order->get_id() );
wc_delete_shop_order_transients( $order );
wp_cache_delete( 'order-' . $order->get_id(), 'orders' );
}
/**

View File

@ -45,6 +45,7 @@ abstract class Abstract_WC_Order_Item_Type_Data_Store extends WC_Data_Store_WP i
$this->save_item_data( $item );
$item->save_meta_data();
$item->apply_changes();
$this->clear_cache( $item );
do_action( 'woocommerce_new_order_item', $item->get_id(), $item, $item->get_order_id() );
}
@ -67,6 +68,7 @@ abstract class Abstract_WC_Order_Item_Type_Data_Store extends WC_Data_Store_WP i
$this->save_item_data( $item );
$item->save_meta_data();
$item->apply_changes();
$this->clear_cache( $item );
do_action( 'woocommerce_update_order_item', $item->get_id(), $item, $item->get_order_id() );
}
@ -121,4 +123,11 @@ abstract class Abstract_WC_Order_Item_Type_Data_Store extends WC_Data_Store_WP i
* @param WC_Order_Item $item
*/
public function save_item_data( &$item ) {}
/**
* Clear meta cachce.
*/
public function clear_cache( &$item ) {
wp_cache_delete( 'order-item-' . $item->get_id(), 'order-items' );
}
}

View File

@ -77,7 +77,8 @@ class WC_Customer_Data_Store extends WC_Data_Store_WP implements WC_Customer_Dat
&& 0 !== strpos( $meta->meta_key, 'closedpostboxes_' )
&& 0 !== strpos( $meta->meta_key, 'metaboxhidden_' )
&& 0 !== strpos( $meta->meta_key, 'manageedit-' )
&& ! strstr( $meta->meta_key, $wpdb->prefix );
&& ! strstr( $meta->meta_key, $wpdb->prefix )
&& 0 !== stripos( $meta->meta_key, 'wp_' );
}
/**

View File

@ -64,9 +64,10 @@ class WC_Data_Store_WP {
global $wpdb;
$db_info = $this->get_db_info();
$raw_meta_data = $wpdb->get_results( $wpdb->prepare( "
SELECT " . $db_info['meta_id_field'] . " as meta_id, meta_key, meta_value
FROM " . $db_info['table'] . "
WHERE " . $db_info['object_id_field'] . "=%d AND meta_key NOT LIKE 'wp\_%%' ORDER BY " . $db_info['meta_id_field'] . "
SELECT {$db_info['meta_id_field']} as meta_id, meta_key, meta_value
FROM {$db_info['table']}
WHERE {$db_info['object_id_field']} = %d
ORDER BY {$db_info['meta_id_field']}
", $object->get_id() ) );
$this->internal_meta_keys = array_merge( array_map( array( $this, 'prefix_key' ), $object->get_data_keys() ), $this->internal_meta_keys );
@ -162,7 +163,7 @@ class WC_Data_Store_WP {
* @return bool
*/
protected function exclude_internal_meta_keys( $meta ) {
return ! in_array( $meta->meta_key, $this->internal_meta_keys );
return ! in_array( $meta->meta_key, $this->internal_meta_keys ) && 0 !== stripos( $meta->meta_key, 'wp_' );
}
/**

View File

@ -142,6 +142,7 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
*/
protected function update_post_meta( &$order ) {
$updated_props = array();
$id = $order->get_id();
$meta_key_to_props = array(
'_order_key' => 'order_key',
'_customer_user' => 'customer_id',
@ -159,7 +160,7 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
$props_to_update = $this->get_props_to_update( $order, $meta_key_to_props );
foreach ( $props_to_update as $meta_key => $prop ) {
$value = $order->{"get_$prop"}( 'edit' );
update_post_meta( $order->get_id(), $meta_key, $value );
update_post_meta( $id, $meta_key, $value );
$updated_props[] = $prop;
}
@ -194,7 +195,7 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
$props_to_update = $this->get_props_to_update( $order, $props );
foreach ( $props_to_update as $meta_key => $prop ) {
$value = $order->{"get_$prop"}( 'edit' );
update_post_meta( $order->get_id(), $meta_key, $value );
update_post_meta( $id, $meta_key, $value );
$updated_props[] = $prop;
$updated_props[] = $props_key;
}
@ -203,17 +204,17 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
parent::update_post_meta( $order );
// If address changed, store concatinated version to make searches faster.
if ( in_array( 'billing', $updated_props ) || ! metadata_exists( 'post', $order->get_id(), '_billing_address_index' ) ) {
update_post_meta( $order->get_id(), '_billing_address_index', implode( ' ', $order->get_address( 'billing' ) ) );
if ( in_array( 'billing', $updated_props ) || ! metadata_exists( 'post', $id, '_billing_address_index' ) ) {
update_post_meta( $id, '_billing_address_index', implode( ' ', $order->get_address( 'billing' ) ) );
}
if ( in_array( 'shipping', $updated_props ) || ! metadata_exists( 'post', $order->get_id(), '_shipping_address_index' ) ) {
update_post_meta( $order->get_id(), '_shipping_address_index', implode( ' ', $order->get_address( 'shipping' ) ) );
if ( in_array( 'shipping', $updated_props ) || ! metadata_exists( 'post', $id, '_shipping_address_index' ) ) {
update_post_meta( $id, '_shipping_address_index', implode( ' ', $order->get_address( 'shipping' ) ) );
}
// If customer changed, update any downloadable permissions.
if ( in_array( 'customer_user', $updated_props ) || in_array( 'billing_email', $updated_props ) ) {
$data_store = WC_Data_Store::load( 'customer-download' );
$data_store->update_user_by_order_id( $order->get_id(), $order->get_customer_id(), $order->get_billing_email() );
$data_store->update_user_by_order_id( $id, $order->get_customer_id(), $order->get_billing_email() );
}
do_action( 'woocommerce_order_object_updated_props', $order, $updated_props );

View File

@ -27,9 +27,10 @@ class WC_Order_Item_Coupon_Data_Store extends Abstract_WC_Order_Item_Type_Data_S
*/
public function read( &$item ) {
parent::read( $item );
$id = $item->get_id();
$item->set_props( array(
'discount' => get_metadata( 'order_item', $item->get_id(), 'discount_amount', true ),
'discount_tax' => get_metadata( 'order_item', $item->get_id(), 'discount_amount_tax', true ),
'discount' => get_metadata( 'order_item', $id, 'discount_amount', true ),
'discount_tax' => get_metadata( 'order_item', $id, 'discount_amount_tax', true ),
) );
$item->set_object_read( true );
}
@ -42,7 +43,13 @@ class WC_Order_Item_Coupon_Data_Store extends Abstract_WC_Order_Item_Type_Data_S
* @param WC_Order_Item $item
*/
public function save_item_data( &$item ) {
wc_update_order_item_meta( $item->get_id(), 'discount_amount', $item->get_discount( 'edit' ) );
wc_update_order_item_meta( $item->get_id(), 'discount_amount_tax', $item->get_discount_tax( 'edit' ) );
$id = $item->get_id();
$save_values = array(
'discount_amount' => $item->get_discount( 'edit' ),
'discount_amount_tax' => $item->get_discount_tax( 'edit' ),
);
foreach ( $save_values as $key => $value ) {
update_metadata( 'order_item', $id, $key, $value );
}
}
}

View File

@ -4,7 +4,7 @@ if ( ! defined( 'ABSPATH' ) ) {
}
/**
* WC Order Item Coupon Data Store: Misc Order Item Data functions.
* WC Order Item Data Store: Misc Order Item Data functions.
*
* @version 2.7.0
* @category Class
@ -74,7 +74,7 @@ class WC_Order_Item_Data_Store implements WC_Order_Item_Data_Store_Interface {
* @param string $prev_value (default: '')
* @return bool
*/
function update_metadata( $item_id, $meta_key, $meta_value, $prev_value = '' ) {
public function update_metadata( $item_id, $meta_key, $meta_value, $prev_value = '' ) {
return update_metadata( 'order_item', $item_id, $meta_key, $meta_value, $prev_value );
}
@ -88,7 +88,7 @@ class WC_Order_Item_Data_Store implements WC_Order_Item_Data_Store_Interface {
* @param bool $unique (default: false)
* @return int New row ID or 0
*/
function add_metadata( $item_id, $meta_key, $meta_value, $unique = false ) {
public function add_metadata( $item_id, $meta_key, $meta_value, $unique = false ) {
return add_metadata( 'order_item', $item_id, $meta_key, $meta_value, $unique );
}
@ -102,7 +102,7 @@ class WC_Order_Item_Data_Store implements WC_Order_Item_Data_Store_Interface {
* @param bool $delete_all (default: false)
* @return bool
*/
function delete_metadata( $item_id, $meta_key, $meta_value = '', $delete_all = false ) {
public function delete_metadata( $item_id, $meta_key, $meta_value = '', $delete_all = false ) {
return delete_metadata( 'order_item', $item_id, $meta_key, $meta_value, $delete_all );
}
@ -115,7 +115,7 @@ class WC_Order_Item_Data_Store implements WC_Order_Item_Data_Store_Interface {
* @param bool $single (default: true)
* @return mixed
*/
function get_metadata( $item_id, $key, $single = true ) {
public function get_metadata( $item_id, $key, $single = true ) {
return get_metadata( 'order_item', $item_id, $key, $single );
}

View File

@ -26,27 +26,34 @@ class WC_Order_Item_Fee_Data_Store extends Abstract_WC_Order_Item_Type_Data_Stor
*/
public function read( &$item ) {
parent::read( $item );
$id = $item->get_id();
$item->set_props( array(
'tax_class' => get_metadata( 'order_item', $item->get_id(), '_tax_class', true ),
'tax_status' => get_metadata( 'order_item', $item->get_id(), '_tax_status', true ),
'total' => get_metadata( 'order_item', $item->get_id(), '_line_total', true ),
'taxes' => get_metadata( 'order_item', $item->get_id(), '_line_tax_data', true ),
'tax_class' => get_metadata( 'order_item', $id, '_tax_class', true ),
'tax_status' => get_metadata( 'order_item', $id, '_tax_status', true ),
'total' => get_metadata( 'order_item', $id, '_line_total', true ),
'taxes' => get_metadata( 'order_item', $id, '_line_tax_data', true ),
) );
$item->set_object_read( true );
}
/**
* Saves an item's data to the database / item meta.
* Ran after both create and update, so $item->get_id() will be set.
* Ran after both create and update, so $id will be set.
*
* @since 2.7.0
* @param WC_Order_Item $item
*/
public function save_item_data( &$item ) {
wc_update_order_item_meta( $item->get_id(), '_tax_class', $item->get_tax_class( 'edit' ) );
wc_update_order_item_meta( $item->get_id(), '_tax_status', $item->get_tax_status( 'edit' ) );
wc_update_order_item_meta( $item->get_id(), '_line_total', $item->get_total( 'edit' ) );
wc_update_order_item_meta( $item->get_id(), '_line_tax', $item->get_total_tax( 'edit' ) );
wc_update_order_item_meta( $item->get_id(), '_line_tax_data', $item->get_taxes( 'edit' ) );
$id = $item->get_id();
$save_values = array(
'_tax_class' => $item->get_tax_class( 'edit' ),
'_tax_status' => $item->get_tax_status( 'edit' ),
'_line_total' => $item->get_total( 'edit' ),
'_line_tax' => $item->get_total_tax( 'edit' ),
'_line_tax_data' => $item->get_taxes( 'edit' ),
);
foreach ( $save_values as $key => $value ) {
update_metadata( 'order_item', $id, $key, $value );
}
}
}

View File

@ -26,35 +26,42 @@ class WC_Order_Item_Product_Data_Store extends Abstract_WC_Order_Item_Type_Data_
*/
public function read( &$item ) {
parent::read( $item );
$id = $item->get_id();
$item->set_props( array(
'product_id' => get_metadata( 'order_item', $item->get_id(), '_product_id', true ),
'variation_id' => get_metadata( 'order_item', $item->get_id(), '_variation_id', true ),
'quantity' => get_metadata( 'order_item', $item->get_id(), '_qty', true ),
'tax_class' => get_metadata( 'order_item', $item->get_id(), '_tax_class', true ),
'subtotal' => get_metadata( 'order_item', $item->get_id(), '_line_subtotal', true ),
'total' => get_metadata( 'order_item', $item->get_id(), '_line_total', true ),
'taxes' => get_metadata( 'order_item', $item->get_id(), '_line_tax_data', true ),
'product_id' => get_metadata( 'order_item', $id, '_product_id', true ),
'variation_id' => get_metadata( 'order_item', $id, '_variation_id', true ),
'quantity' => get_metadata( 'order_item', $id, '_qty', true ),
'tax_class' => get_metadata( 'order_item', $id, '_tax_class', true ),
'subtotal' => get_metadata( 'order_item', $id, '_line_subtotal', true ),
'total' => get_metadata( 'order_item', $id, '_line_total', true ),
'taxes' => get_metadata( 'order_item', $id, '_line_tax_data', true ),
) );
$item->set_object_read( true );
}
/**
* Saves an item's data to the database / item meta.
* Ran after both create and update, so $item->get_id() will be set.
* Ran after both create and update, so $id will be set.
*
* @since 2.7.0
* @param WC_Order_Item $item
*/
public function save_item_data( &$item ) {
wc_update_order_item_meta( $item->get_id(), '_product_id', $item->get_product_id( 'edit' ) );
wc_update_order_item_meta( $item->get_id(), '_variation_id', $item->get_variation_id( 'edit' ) );
wc_update_order_item_meta( $item->get_id(), '_qty', $item->get_quantity( 'edit' ) );
wc_update_order_item_meta( $item->get_id(), '_tax_class', $item->get_tax_class( 'edit' ) );
wc_update_order_item_meta( $item->get_id(), '_line_subtotal', $item->get_subtotal( 'edit' ) );
wc_update_order_item_meta( $item->get_id(), '_line_subtotal_tax', $item->get_subtotal_tax( 'edit' ) );
wc_update_order_item_meta( $item->get_id(), '_line_total', $item->get_total( 'edit' ) );
wc_update_order_item_meta( $item->get_id(), '_line_tax', $item->get_total_tax( 'edit' ) );
wc_update_order_item_meta( $item->get_id(), '_line_tax_data', $item->get_taxes( 'edit' ) );
$id = $item->get_id();
$save_values = array(
'_product_id' => $item->get_product_id( 'edit' ),
'_variation_id' => $item->get_variation_id( 'edit' ),
'_qty' => $item->get_quantity( 'edit' ),
'_tax_class' => $item->get_tax_class( 'edit' ),
'_line_subtotal' => $item->get_subtotal( 'edit' ),
'_line_subtotal_tax' => $item->get_subtotal_tax( 'edit' ),
'_line_total' => $item->get_total( 'edit' ),
'_line_tax' => $item->get_total_tax( 'edit' ),
'_line_tax_data' => $item->get_taxes( 'edit' ),
);
foreach ( $save_values as $key => $value ) {
update_metadata( 'order_item', $id, $key, $value );
}
}
/**

View File

@ -26,25 +26,32 @@ class WC_Order_Item_Shipping_Data_Store extends Abstract_WC_Order_Item_Type_Data
*/
public function read( &$item ) {
parent::read( $item );
$id = $item->get_id();
$item->set_props( array(
'method_id' => get_metadata( 'order_item', $item->get_id(), 'method_id', true ),
'total' => get_metadata( 'order_item', $item->get_id(), 'cost', true ),
'taxes' => get_metadata( 'order_item', $item->get_id(), 'taxes', true ),
'method_id' => get_metadata( 'order_item', $id, 'method_id', true ),
'total' => get_metadata( 'order_item', $id, 'cost', true ),
'taxes' => get_metadata( 'order_item', $id, 'taxes', true ),
) );
$item->set_object_read( true );
}
/**
* Saves an item's data to the database / item meta.
* Ran after both create and update, so $item->get_id() will be set.
* Ran after both create and update, so $id will be set.
*
* @since 2.7.0
* @param WC_Order_Item $item
*/
public function save_item_data( &$item ) {
wc_update_order_item_meta( $item->get_id(), 'method_id', $item->get_method_id( 'edit' ) );
wc_update_order_item_meta( $item->get_id(), 'cost', $item->get_total( 'edit' ) );
wc_update_order_item_meta( $item->get_id(), 'total_tax', $item->get_total_tax( 'edit' ) );
wc_update_order_item_meta( $item->get_id(), 'taxes', $item->get_taxes( 'edit' ) );
$id = $item->get_id();
$save_values = array(
'method_id' => $item->get_method_id( 'edit' ),
'cost' => $item->get_total( 'edit' ),
'total_tax' => $item->get_total_tax( 'edit' ),
'taxes' => $item->get_taxes( 'edit' ),
);
foreach ( $save_values as $key => $value ) {
update_metadata( 'order_item', $id, $key, $value );
}
}
}

View File

@ -26,28 +26,35 @@ class WC_Order_Item_Tax_Data_Store extends Abstract_WC_Order_Item_Type_Data_Stor
*/
public function read( &$item ) {
parent::read( $item );
$id = $item->get_id();
$item->set_props( array(
'rate_id' => get_metadata( 'order_item', $item->get_id(), 'rate_id', true ),
'label' => get_metadata( 'order_item', $item->get_id(), 'label', true ),
'compound' => get_metadata( 'order_item', $item->get_id(), 'compound', true ),
'tax_total' => get_metadata( 'order_item', $item->get_id(), 'tax_amount', true ),
'shipping_tax_total' => get_metadata( 'order_item', $item->get_id(), 'shipping_tax_amount', true ),
'rate_id' => get_metadata( 'order_item', $id, 'rate_id', true ),
'label' => get_metadata( 'order_item', $id, 'label', true ),
'compound' => get_metadata( 'order_item', $id, 'compound', true ),
'tax_total' => get_metadata( 'order_item', $id, 'tax_amount', true ),
'shipping_tax_total' => get_metadata( 'order_item', $id, 'shipping_tax_amount', true ),
) );
$item->set_object_read( true );
}
/**
* Saves an item's data to the database / item meta.
* Ran after both create and update, so $item->get_id() will be set.
* Ran after both create and update, so $id will be set.
*
* @since 2.7.0
* @param WC_Order_Item $item
*/
public function save_item_data( &$item ) {
wc_update_order_item_meta( $item->get_id(), 'rate_id', $item->get_rate_id( 'edit' ) );
wc_update_order_item_meta( $item->get_id(), 'label', $item->get_label( 'edit' ) );
wc_update_order_item_meta( $item->get_id(), 'compound', $item->get_compound( 'edit' ) );
wc_update_order_item_meta( $item->get_id(), 'tax_amount', $item->get_tax_total( 'edit' ) );
wc_update_order_item_meta( $item->get_id(), 'shipping_tax_amount', $item->get_shipping_tax_total( 'edit' ) );
$id = $item->get_id();
$save_values = array(
'rate_id' => $item->get_rate_id( 'edit' ),
'label' => $item->get_label( 'edit' ),
'compound' => $item->get_compound( 'edit' ),
'tax_amount' => $item->get_tax_total( 'edit' ),
'shipping_tax_amount' => $item->get_shipping_tax_total( 'edit' ),
);
foreach ( $save_values as $key => $value ) {
update_metadata( 'order_item', $id, $key, $value );
}
}
}

View File

@ -19,7 +19,7 @@ class WC_Product_Variation_Data_Store_CPT extends WC_Product_Data_Store_CPT impl
* @return bool false if excluded.
*/
protected function exclude_internal_meta_keys( $meta ) {
return ! in_array( $meta->meta_key, $this->internal_meta_keys ) && 0 !== stripos( $meta->meta_key, 'attribute_' );
return ! in_array( $meta->meta_key, $this->internal_meta_keys ) && 0 !== stripos( $meta->meta_key, 'attribute_' ) && 0 !== stripos( $meta->meta_key, 'wp_' );
}
/*

View File

@ -32,8 +32,8 @@ class WC_Email_Cancelled_Order extends WC_Email {
$this->template_plain = 'emails/plain/admin-cancelled-order.php';
// Triggers for this email
add_action( 'woocommerce_order_status_pending_to_cancelled_notification', array( $this, 'trigger' ) );
add_action( 'woocommerce_order_status_on-hold_to_cancelled_notification', array( $this, 'trigger' ) );
add_action( 'woocommerce_order_status_pending_to_cancelled_notification', array( $this, 'trigger' ), 10, 2 );
add_action( 'woocommerce_order_status_on-hold_to_cancelled_notification', array( $this, 'trigger' ), 10, 2 );
// Call parent constructor
parent::__construct();
@ -46,10 +46,11 @@ class WC_Email_Cancelled_Order extends WC_Email {
* Trigger.
*
* @param int $order_id
* @param WC_Order $order
*/
public function trigger( $order_id ) {
if ( $order_id ) {
$this->object = wc_get_order( $order_id );
public function trigger( $order_id, $order ) {
if ( $order ) {
$this->object = $order;
$this->find['order-date'] = '{order_date}';
$this->find['order-number'] = '{order_number}';
$this->replace['order-date'] = date_i18n( wc_date_format(), $this->object->get_date_created() );

View File

@ -36,7 +36,7 @@ class WC_Email_Customer_Completed_Order extends WC_Email {
$this->template_plain = 'emails/plain/customer-completed-order.php';
// Triggers for this email
add_action( 'woocommerce_order_status_completed_notification', array( $this, 'trigger' ) );
add_action( 'woocommerce_order_status_completed_notification', array( $this, 'trigger' ), 10, 2 );
// Other settings
$this->heading_downloadable = $this->get_option( 'heading_downloadable', __( 'Your order is complete - download your files', 'woocommerce' ) );
@ -50,11 +50,11 @@ class WC_Email_Customer_Completed_Order extends WC_Email {
* Trigger.
*
* @param int $order_id
* @param WC_Order $order
*/
public function trigger( $order_id ) {
if ( $order_id ) {
$this->object = wc_get_order( $order_id );
public function trigger( $order_id, $order ) {
if ( $order ) {
$this->object = $order;
$this->recipient = $this->object->get_billing_email();
$this->find['order-date'] = '{order_date}';

View File

@ -33,8 +33,8 @@ class WC_Email_Customer_On_Hold_Order extends WC_Email {
$this->template_plain = 'emails/plain/customer-on-hold-order.php';
// Triggers for this email
add_action( 'woocommerce_order_status_pending_to_on-hold_notification', array( $this, 'trigger' ) );
add_action( 'woocommerce_order_status_failed_to_on-hold_notification', array( $this, 'trigger' ) );
add_action( 'woocommerce_order_status_pending_to_on-hold_notification', array( $this, 'trigger' ), 10, 2 );
add_action( 'woocommerce_order_status_failed_to_on-hold_notification', array( $this, 'trigger' ), 10, 2 );
// Call parent constructor
parent::__construct();
@ -44,11 +44,11 @@ class WC_Email_Customer_On_Hold_Order extends WC_Email {
* Trigger.
*
* @param int $order_id
* @param WC_Order $order
*/
public function trigger( $order_id ) {
if ( $order_id ) {
$this->object = wc_get_order( $order_id );
public function trigger( $order_id, $order ) {
if ( $order ) {
$this->object = $order;
$this->recipient = $this->object->get_billing_email();
$this->find['order-date'] = '{order_date}';
@ -77,7 +77,7 @@ class WC_Email_Customer_On_Hold_Order extends WC_Email {
'email_heading' => $this->get_heading(),
'sent_to_admin' => false,
'plain_text' => false,
'email' => $this,
'email' => $this,
) );
}

View File

@ -33,8 +33,8 @@ class WC_Email_Customer_Processing_Order extends WC_Email {
$this->template_plain = 'emails/plain/customer-processing-order.php';
// Triggers for this email
add_action( 'woocommerce_order_status_on-hold_to_processing_notification', array( $this, 'trigger' ) );
add_action( 'woocommerce_order_status_pending_to_processing_notification', array( $this, 'trigger' ) );
add_action( 'woocommerce_order_status_on-hold_to_processing_notification', array( $this, 'trigger' ), 10, 2 );
add_action( 'woocommerce_order_status_pending_to_processing_notification', array( $this, 'trigger' ), 10, 2 );
// Call parent constructor
parent::__construct();
@ -44,11 +44,11 @@ class WC_Email_Customer_Processing_Order extends WC_Email {
* Trigger.
*
* @param int $order_id
* @param WC_Order $order
*/
public function trigger( $order_id ) {
if ( $order_id ) {
$this->object = wc_get_order( $order_id );
public function trigger( $order_id, $order ) {
if ( $order ) {
$this->object = $order;
$this->recipient = $this->object->get_billing_email();
$this->find['order-date'] = '{order_date}';

View File

@ -32,8 +32,8 @@ class WC_Email_Failed_Order extends WC_Email {
$this->template_plain = 'emails/plain/admin-failed-order.php';
// Triggers for this email
add_action( 'woocommerce_order_status_pending_to_failed_notification', array( $this, 'trigger' ) );
add_action( 'woocommerce_order_status_on-hold_to_failed_notification', array( $this, 'trigger' ) );
add_action( 'woocommerce_order_status_pending_to_failed_notification', array( $this, 'trigger' ), 10, 2 );
add_action( 'woocommerce_order_status_on-hold_to_failed_notification', array( $this, 'trigger' ), 10, 2 );
// Call parent constructor
parent::__construct();
@ -46,10 +46,11 @@ class WC_Email_Failed_Order extends WC_Email {
* Trigger.
*
* @param int $order_id
* @param WC_Order $order
*/
public function trigger( $order_id ) {
if ( $order_id ) {
$this->object = wc_get_order( $order_id );
public function trigger( $order_id, $order ) {
if ( $order ) {
$this->object = $order;
$this->find['order-date'] = '{order_date}';
$this->find['order-number'] = '{order_number}';
$this->replace['order-date'] = date_i18n( wc_date_format(), $this->object->get_date_created() );

View File

@ -32,12 +32,12 @@ class WC_Email_New_Order extends WC_Email {
$this->template_plain = 'emails/plain/admin-new-order.php';
// Triggers for this email
add_action( 'woocommerce_order_status_pending_to_processing_notification', array( $this, 'trigger' ) );
add_action( 'woocommerce_order_status_pending_to_completed_notification', array( $this, 'trigger' ) );
add_action( 'woocommerce_order_status_pending_to_on-hold_notification', array( $this, 'trigger' ) );
add_action( 'woocommerce_order_status_failed_to_processing_notification', array( $this, 'trigger' ) );
add_action( 'woocommerce_order_status_failed_to_completed_notification', array( $this, 'trigger' ) );
add_action( 'woocommerce_order_status_failed_to_on-hold_notification', array( $this, 'trigger' ) );
add_action( 'woocommerce_order_status_pending_to_processing_notification', array( $this, 'trigger' ), 10, 2 );
add_action( 'woocommerce_order_status_pending_to_completed_notification', array( $this, 'trigger' ), 10, 2 );
add_action( 'woocommerce_order_status_pending_to_on-hold_notification', array( $this, 'trigger' ), 10, 2 );
add_action( 'woocommerce_order_status_failed_to_processing_notification', array( $this, 'trigger' ), 10, 2 );
add_action( 'woocommerce_order_status_failed_to_completed_notification', array( $this, 'trigger' ), 10, 2 );
add_action( 'woocommerce_order_status_failed_to_on-hold_notification', array( $this, 'trigger' ), 10, 2 );
// Call parent constructor
parent::__construct();
@ -50,10 +50,11 @@ class WC_Email_New_Order extends WC_Email {
* Trigger.
*
* @param int $order_id
* @param WC_Order $order
*/
public function trigger( $order_id ) {
if ( $order_id ) {
$this->object = wc_get_order( $order_id );
public function trigger( $order_id, $order ) {
if ( $order ) {
$this->object = $order;
$this->find['order-date'] = '{order_date}';
$this->find['order-number'] = '{order_number}';
$this->replace['order-date'] = date_i18n( wc_date_format(), $this->object->get_date_created() );

View File

@ -174,6 +174,7 @@ final class WooCommerce {
add_action( 'init', array( $this, 'init' ), 0 );
add_action( 'init', array( 'WC_Shortcodes', 'init' ) );
add_action( 'init', array( 'WC_Emails', 'init_transactional_emails' ) );
add_action( 'woocommerce_send_queued_transactional_email', array( 'WC_Emails', 'send_queued_transactional_email' ), 10, 2 );
add_action( 'init', array( $this, 'wpdb_table_fix' ), 0 );
add_action( 'switch_blog', array( $this, 'wpdb_table_fix' ), 0 );
}