Merge branch 'master' into fix/28232
This commit is contained in:
commit
246710fce8
10
.travis.yml
10
.travis.yml
|
@ -88,3 +88,13 @@ branches:
|
||||||
- master
|
- master
|
||||||
- /^\d+\.\d+(\.\d+)?(-\S*)?$/
|
- /^\d+\.\d+(\.\d+)?(-\S*)?$/
|
||||||
- /^release\//
|
- /^release\//
|
||||||
|
|
||||||
|
# Composer 2.0.7 introduced a change that broke the jetpack autoloader in PHP 7.0 - 7.3.
|
||||||
|
before_install:
|
||||||
|
- composer self-update 2.0.6
|
||||||
|
|
||||||
|
# Git clone depth
|
||||||
|
# By default Travis CI clones repositories to a depth of 50 commits. Using a depth of 1 makes this step a bit faster.
|
||||||
|
git:
|
||||||
|
depth: 1
|
||||||
|
|
||||||
|
|
|
@ -507,9 +507,8 @@ jQuery( function( $ ) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
url: wc_checkout_params.checkout_url,
|
url: wc_checkout_params.checkout_url,
|
||||||
data: new FormData( this ),
|
data: $form.serialize(),
|
||||||
contentType: false,
|
dataType: 'json',
|
||||||
processData: false,
|
|
||||||
success: function( result ) {
|
success: function( result ) {
|
||||||
// Detach the unload handler that prevents a reload / redirect
|
// Detach the unload handler that prevents a reload / redirect
|
||||||
wc_checkout_form.detachUnloadEventsOnSubmit();
|
wc_checkout_form.detachUnloadEventsOnSubmit();
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "928d8825a02fc4217b3af36a83c2fbc8",
|
"content-hash": "6494b4d4b956386e32381541ebd79839",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "automattic/jetpack-autoloader",
|
"name": "automattic/jetpack-autoloader",
|
||||||
|
@ -493,22 +493,27 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/css-selector",
|
"name": "symfony/css-selector",
|
||||||
"version": "v3.4.46",
|
"version": "v3.3.6",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/css-selector.git",
|
"url": "https://github.com/symfony/css-selector.git",
|
||||||
"reference": "da3d9da2ce0026771f5fe64cb332158f1bd2bc33"
|
"reference": "4d882dced7b995d5274293039370148e291808f2"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/css-selector/zipball/da3d9da2ce0026771f5fe64cb332158f1bd2bc33",
|
"url": "https://api.github.com/repos/symfony/css-selector/zipball/4d882dced7b995d5274293039370148e291808f2",
|
||||||
"reference": "da3d9da2ce0026771f5fe64cb332158f1bd2bc33",
|
"reference": "4d882dced7b995d5274293039370148e291808f2",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^5.5.9|>=7.0.8"
|
"php": ">=5.5.9"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "3.3-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"Symfony\\Component\\CssSelector\\": ""
|
"Symfony\\Component\\CssSelector\\": ""
|
||||||
|
@ -522,14 +527,14 @@
|
||||||
"MIT"
|
"MIT"
|
||||||
],
|
],
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
|
||||||
"name": "Fabien Potencier",
|
|
||||||
"email": "fabien@symfony.com"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "Jean-François Simon",
|
"name": "Jean-François Simon",
|
||||||
"email": "jeanfrancois.simon@sensiolabs.com"
|
"email": "jeanfrancois.simon@sensiolabs.com"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "Fabien Potencier",
|
||||||
|
"email": "fabien@symfony.com"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Symfony Community",
|
"name": "Symfony Community",
|
||||||
"homepage": "https://symfony.com/contributors"
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
@ -538,23 +543,9 @@
|
||||||
"description": "Symfony CssSelector Component",
|
"description": "Symfony CssSelector Component",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/css-selector/tree/v3.4.46"
|
"source": "https://github.com/symfony/css-selector/tree/master"
|
||||||
},
|
},
|
||||||
"funding": [
|
"time": "2017-05-01T15:01:29+00:00"
|
||||||
{
|
|
||||||
"url": "https://symfony.com/sponsor",
|
|
||||||
"type": "custom"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://github.com/fabpot",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
|
||||||
"type": "tidelift"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"time": "2020-10-24T10:57:07+00:00"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "woocommerce/action-scheduler",
|
"name": "woocommerce/action-scheduler",
|
||||||
|
@ -758,7 +749,7 @@
|
||||||
},
|
},
|
||||||
"platform-dev": [],
|
"platform-dev": [],
|
||||||
"platform-overrides": {
|
"platform-overrides": {
|
||||||
"php": "7.1"
|
"php": "7.0"
|
||||||
},
|
},
|
||||||
"plugin-api-version": "2.0.0"
|
"plugin-api-version": "2.0.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -519,6 +519,50 @@ abstract class WC_Data {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method to compute meta cache key. Different from WP Meta cache key in that meta data cached using this key also contains meta_id column.
|
||||||
|
*
|
||||||
|
* @since 4.7.0
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function get_meta_cache_key() {
|
||||||
|
if ( ! $this->get_id() ) {
|
||||||
|
wc_doing_it_wrong( 'get_meta_cache_key', 'ID needs to be set before fetching a cache key.', '4.7.0' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return self::generate_meta_cache_key( $this->get_id(), $this->cache_group );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate cache key from id and group.
|
||||||
|
*
|
||||||
|
* @since 4.7.0
|
||||||
|
*
|
||||||
|
* @param int|string $id Object ID.
|
||||||
|
* @param string $cache_group Group name use to store cache. Whole group cache can be invalidated in one go.
|
||||||
|
*
|
||||||
|
* @return string Meta cache key.
|
||||||
|
*/
|
||||||
|
public static function generate_meta_cache_key( $id, $cache_group ) {
|
||||||
|
return WC_Cache_Helper::get_cache_prefix( $cache_group ) . WC_Cache_Helper::get_cache_prefix( 'object_' . $id ) . 'object_meta_' . $id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prime caches for raw meta data. This includes meta_id column as well, which is not included by default in WP meta data.
|
||||||
|
*
|
||||||
|
* @since 4.7.0
|
||||||
|
*
|
||||||
|
* @param array $raw_meta_data_collection Array of objects of { object_id => array( meta_row_1, meta_row_2, ... }.
|
||||||
|
* @param string $cache_group Name of cache group.
|
||||||
|
*/
|
||||||
|
public static function prime_raw_meta_data_cache( $raw_meta_data_collection, $cache_group ) {
|
||||||
|
foreach ( $raw_meta_data_collection as $object_id => $raw_meta_data_array ) {
|
||||||
|
$cache_key = self::generate_meta_cache_key( $object_id, $cache_group );
|
||||||
|
wp_cache_set( $cache_key, $raw_meta_data_array, $cache_group );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read Meta Data from the database. Ignore any internal properties.
|
* Read Meta Data from the database. Ignore any internal properties.
|
||||||
* Uses it's own caches because get_metadata does not provide meta_ids.
|
* Uses it's own caches because get_metadata does not provide meta_ids.
|
||||||
|
@ -540,7 +584,7 @@ abstract class WC_Data {
|
||||||
|
|
||||||
if ( ! empty( $this->cache_group ) ) {
|
if ( ! empty( $this->cache_group ) ) {
|
||||||
// Prefix by group allows invalidation by group until https://core.trac.wordpress.org/ticket/4476 is implemented.
|
// Prefix by group allows invalidation by group until https://core.trac.wordpress.org/ticket/4476 is implemented.
|
||||||
$cache_key = WC_Cache_Helper::get_cache_prefix( $this->cache_group ) . WC_Cache_Helper::get_cache_prefix( 'object_' . $this->get_id() ) . 'object_meta_' . $this->get_id();
|
$cache_key = $this->get_meta_cache_key();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! $force_read ) {
|
if ( ! $force_read ) {
|
||||||
|
@ -550,7 +594,9 @@ abstract class WC_Data {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$raw_meta_data = $cache_loaded ? $cached_meta : $this->data_store->read_meta( $this );
|
// We filter the raw meta data again when loading from cache, in case we cached in an earlier version where filter conditions were different.
|
||||||
|
$raw_meta_data = $cache_loaded ? $this->data_store->filter_raw_meta_data( $this, $cached_meta ) : $this->data_store->read_meta( $this );
|
||||||
|
|
||||||
if ( $raw_meta_data ) {
|
if ( $raw_meta_data ) {
|
||||||
foreach ( $raw_meta_data as $meta ) {
|
foreach ( $raw_meta_data as $meta ) {
|
||||||
$this->meta_data[] = new WC_Meta_Data(
|
$this->meta_data[] = new WC_Meta_Data(
|
||||||
|
|
|
@ -57,6 +57,10 @@ class WC_Helper_Updater {
|
||||||
'upgrade_notice' => $data['upgrade_notice'],
|
'upgrade_notice' => $data['upgrade_notice'],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if ( isset( $data['requires_php'] ) ) {
|
||||||
|
$item['requires_php'] = $data['requires_php'];
|
||||||
|
}
|
||||||
|
|
||||||
// We don't want to deliver a valid upgrade package when their subscription has expired.
|
// We don't want to deliver a valid upgrade package when their subscription has expired.
|
||||||
// To avoid the generic "no_package" error that empty strings give, we will store an
|
// To avoid the generic "no_package" error that empty strings give, we will store an
|
||||||
// indication of expiration for the `upgrader_pre_download` filter to error on.
|
// indication of expiration for the `upgrader_pre_download` filter to error on.
|
||||||
|
|
|
@ -22,7 +22,7 @@ final class WooCommerce {
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
public $version = '4.8.0';
|
public $version = '4.9.0';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* WooCommerce Schema version.
|
* WooCommerce Schema version.
|
||||||
|
|
|
@ -93,14 +93,13 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
|
||||||
/**
|
/**
|
||||||
* Method to read an order from the database.
|
* Method to read an order from the database.
|
||||||
*
|
*
|
||||||
* @param WC_Data $order Order object.
|
* @param WC_Order $order Order object.
|
||||||
*
|
*
|
||||||
* @throws Exception If passed order is invalid.
|
* @throws Exception If passed order is invalid.
|
||||||
*/
|
*/
|
||||||
public function read( &$order ) {
|
public function read( &$order ) {
|
||||||
$order->set_defaults();
|
$order->set_defaults();
|
||||||
$post_object = get_post( $order->get_id() );
|
$post_object = get_post( $order->get_id() );
|
||||||
|
|
||||||
if ( ! $order->get_id() || ! $post_object || ! in_array( $post_object->post_type, wc_get_order_types(), true ) ) {
|
if ( ! $order->get_id() || ! $post_object || ! in_array( $post_object->post_type, wc_get_order_types(), true ) ) {
|
||||||
throw new Exception( __( 'Invalid order.', 'woocommerce' ) );
|
throw new Exception( __( 'Invalid order.', 'woocommerce' ) );
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,7 +94,20 @@ class WC_Data_Store_WP {
|
||||||
$object->get_id()
|
$object->get_id()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
return $this->filter_raw_meta_data( $object, $raw_meta_data );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method to filter internal meta keys from all meta data rows for the object.
|
||||||
|
*
|
||||||
|
* @since 4.7.0
|
||||||
|
*
|
||||||
|
* @param WC_Data $object WC_Data object.
|
||||||
|
* @param array $raw_meta_data Array of std object of meta data to be filtered.
|
||||||
|
*
|
||||||
|
* @return mixed|void
|
||||||
|
*/
|
||||||
|
public function filter_raw_meta_data( &$object, $raw_meta_data ) {
|
||||||
$this->internal_meta_keys = array_merge( array_map( array( $this, 'prefix_key' ), $object->get_data_keys() ), $this->internal_meta_keys );
|
$this->internal_meta_keys = array_merge( array_map( array( $this, 'prefix_key' ), $object->get_data_keys() ), $this->internal_meta_keys );
|
||||||
$meta_data = array_filter( $raw_meta_data, array( $this, 'exclude_internal_meta_keys' ) );
|
$meta_data = array_filter( $raw_meta_data, array( $this, 'exclude_internal_meta_keys' ) );
|
||||||
return apply_filters( "woocommerce_data_store_wp_{$this->meta_type}_read_meta", $meta_data, $object, $this );
|
return apply_filters( "woocommerce_data_store_wp_{$this->meta_type}_read_meta", $meta_data, $object, $this );
|
||||||
|
|
|
@ -734,11 +734,12 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
|
||||||
* Get the order type based on Order ID.
|
* Get the order type based on Order ID.
|
||||||
*
|
*
|
||||||
* @since 3.0.0
|
* @since 3.0.0
|
||||||
* @param int $order_id Order ID.
|
* @param int|WP_Post $order Order | Order id.
|
||||||
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function get_order_type( $order_id ) {
|
public function get_order_type( $order ) {
|
||||||
return get_post_type( $order_id );
|
return get_post_type( $order );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -865,7 +866,13 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
|
||||||
$query = new WP_Query( $args );
|
$query = new WP_Query( $args );
|
||||||
}
|
}
|
||||||
|
|
||||||
$orders = ( isset( $query_vars['return'] ) && 'ids' === $query_vars['return'] ) ? $query->posts : array_filter( array_map( 'wc_get_order', $query->posts ) );
|
if ( isset( $query_vars['return'] ) && 'ids' === $query_vars['return'] ) {
|
||||||
|
$orders = $query->posts;
|
||||||
|
} else {
|
||||||
|
update_post_caches( $query->posts ); // We already fetching posts, might as well hydrate some caches.
|
||||||
|
$order_ids = wp_list_pluck( $query->posts, 'ID' );
|
||||||
|
$orders = $this->compile_orders( $order_ids, $query_vars, $query );
|
||||||
|
}
|
||||||
|
|
||||||
if ( isset( $query_vars['paginate'] ) && $query_vars['paginate'] ) {
|
if ( isset( $query_vars['paginate'] ) && $query_vars['paginate'] ) {
|
||||||
return (object) array(
|
return (object) array(
|
||||||
|
@ -878,6 +885,213 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
|
||||||
return $orders;
|
return $orders;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compile order response and set caches as needed for order ids.
|
||||||
|
*
|
||||||
|
* @param array $order_ids List of order IDS to compile.
|
||||||
|
* @param array $query_vars Original query arguments.
|
||||||
|
* @param WP_Query $query Query object.
|
||||||
|
*
|
||||||
|
* @return array Orders.
|
||||||
|
*/
|
||||||
|
private function compile_orders( $order_ids, $query_vars, $query ) {
|
||||||
|
if ( empty( $order_ids ) ) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
$orders = array();
|
||||||
|
|
||||||
|
// Lets do some cache hydrations so that we don't have to fetch data from DB for every order.
|
||||||
|
$this->prime_raw_meta_cache_for_orders( $order_ids, $query_vars );
|
||||||
|
$this->prime_refund_caches_for_order( $order_ids, $query_vars );
|
||||||
|
$this->prime_order_item_caches_for_orders( $order_ids, $query_vars );
|
||||||
|
|
||||||
|
foreach ( $query->posts as $post ) {
|
||||||
|
$orders[] = wc_get_order( $post );
|
||||||
|
}
|
||||||
|
|
||||||
|
return $orders;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prime refund cache for orders.
|
||||||
|
*
|
||||||
|
* @param array $order_ids Order Ids to prime cache for.
|
||||||
|
* @param array $query_vars Query vars for the query.
|
||||||
|
*/
|
||||||
|
private function prime_refund_caches_for_order( $order_ids, $query_vars ) {
|
||||||
|
if ( ! isset( $query_vars['type'] ) || ! ( 'shop_order' === $query_vars['type'] ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( isset( $query_vars['fields'] ) && 'all' !== $query_vars['fields'] ) {
|
||||||
|
if ( is_array( $query_vars['fields'] ) && ! in_array( 'refunds', $query_vars['fields'] ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$cache_keys_mapping = array();
|
||||||
|
foreach ( $order_ids as $order_id ) {
|
||||||
|
$cache_keys_mapping[ $order_id ] = WC_Cache_Helper::get_cache_prefix( 'orders' ) . 'refunds' . $order_id;
|
||||||
|
}
|
||||||
|
$non_cached_ids = array();
|
||||||
|
$cache_values = wc_cache_get_multiple( array_values( $cache_keys_mapping ), 'orders' );
|
||||||
|
foreach ( $order_ids as $order_id ) {
|
||||||
|
if ( false === $cache_values[ $cache_keys_mapping[ $order_id ] ] ) {
|
||||||
|
$non_cached_ids[] = $order_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( empty( $non_cached_ids ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$refunds = wc_get_orders(
|
||||||
|
array(
|
||||||
|
'type' => 'shop_order_refund',
|
||||||
|
'post_parent__in' => $non_cached_ids,
|
||||||
|
'limit' => - 1,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$order_refunds = array_reduce(
|
||||||
|
$refunds,
|
||||||
|
function ( $order_refunds_array, WC_Order_Refund $refund ) {
|
||||||
|
if ( ! isset( $order_refunds_array[ $refund->get_parent_id() ] ) ) {
|
||||||
|
$order_refunds_array[ $refund->get_parent_id() ] = array();
|
||||||
|
}
|
||||||
|
$order_refunds_array[ $refund->get_parent_id() ][] = $refund;
|
||||||
|
return $order_refunds_array;
|
||||||
|
},
|
||||||
|
array()
|
||||||
|
);
|
||||||
|
foreach ( $non_cached_ids as $order_id ) {
|
||||||
|
$refunds = array();
|
||||||
|
if ( isset( $order_refunds[ $order_id ] ) ) {
|
||||||
|
$refunds = $order_refunds[ $order_id ];
|
||||||
|
}
|
||||||
|
wp_cache_set( $cache_keys_mapping[ $order_id ], $refunds, 'orders' );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prime following caches:
|
||||||
|
* 1. item-$order_item_id For individual items.
|
||||||
|
* 2. order-items-$order-id For fetching items associated with an order.
|
||||||
|
* 3. order-item meta.
|
||||||
|
*
|
||||||
|
* @param array $order_ids Order Ids to prime cache for.
|
||||||
|
* @param array $query_vars Query vars for the query.
|
||||||
|
*/
|
||||||
|
private function prime_order_item_caches_for_orders( $order_ids, $query_vars ) {
|
||||||
|
global $wpdb;
|
||||||
|
if ( isset( $query_vars['fields'] ) && 'all' !== $query_vars['fields'] ) {
|
||||||
|
$line_items = array(
|
||||||
|
'line_items',
|
||||||
|
'shipping_lines',
|
||||||
|
'fee_lines',
|
||||||
|
'coupon_lines',
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( is_array( $query_vars['fields'] ) && 0 === count( array_intersect( $line_items, $query_vars['fields'] ) ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$cache_keys = array_map(
|
||||||
|
function ( $order_id ) {
|
||||||
|
return 'order-items-' . $order_id;
|
||||||
|
},
|
||||||
|
$order_ids
|
||||||
|
);
|
||||||
|
$cache_values = wc_cache_get_multiple( $cache_keys, 'orders' );
|
||||||
|
$non_cached_ids = array();
|
||||||
|
foreach ( $order_ids as $order_id ) {
|
||||||
|
if ( false === $cache_values[ 'order-items-' . $order_id ] ) {
|
||||||
|
$non_cached_ids[] = $order_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( empty( $non_cached_ids ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$non_cached_ids = esc_sql( $non_cached_ids );
|
||||||
|
$non_cached_ids_string = implode( ',', $non_cached_ids );
|
||||||
|
$order_items = $wpdb->get_results(
|
||||||
|
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
||||||
|
"SELECT order_item_type, order_item_id, order_id, order_item_name FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id in ( $non_cached_ids_string ) ORDER BY order_item_id;"
|
||||||
|
);
|
||||||
|
if ( empty( $order_items ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$order_items_for_all_orders = array_reduce(
|
||||||
|
$order_items,
|
||||||
|
function ( $order_items_collection, $order_item ) {
|
||||||
|
if ( ! isset( $order_items_collection[ $order_item->order_id ] ) ) {
|
||||||
|
$order_items_collection[ $order_item->order_id ] = array();
|
||||||
|
}
|
||||||
|
$order_items_collection[ $order_item->order_id ][] = $order_item;
|
||||||
|
return $order_items_collection;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
foreach ( $order_items_for_all_orders as $order_id => $items ) {
|
||||||
|
wp_cache_set( 'order-items-' . $order_id, $items, 'orders' );
|
||||||
|
}
|
||||||
|
foreach ( $order_items as $item ) {
|
||||||
|
wp_cache_set( 'item-' . $item->order_item_id, $item, 'order-items' );
|
||||||
|
}
|
||||||
|
$order_item_ids = wp_list_pluck( $order_items, 'order_item_id' );
|
||||||
|
update_meta_cache( 'order_item', $order_item_ids );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prime cache for raw meta data for orders in bulk. Difference between this and WP built-in metadata is that this method also fetches `meta_id` field which we use and cache it.
|
||||||
|
*
|
||||||
|
* @param array $order_ids Order Ids to prime cache for.
|
||||||
|
* @param array $query_vars Query vars for the query.
|
||||||
|
*/
|
||||||
|
private function prime_raw_meta_cache_for_orders( $order_ids, $query_vars ) {
|
||||||
|
global $wpdb;
|
||||||
|
|
||||||
|
if ( isset( $query_vars['fields'] ) && 'all' !== $query_vars['fields'] ) {
|
||||||
|
if ( is_array( $query_vars['fields'] ) && ! in_array( 'meta_data', $query_vars['fields'] ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$cache_keys_mapping = array();
|
||||||
|
foreach ( $order_ids as $order_id ) {
|
||||||
|
$cache_keys_mapping[ $order_id ] = WC_Order::generate_meta_cache_key( $order_id, 'orders' );
|
||||||
|
}
|
||||||
|
$cache_values = wc_cache_get_multiple( array_values( $cache_keys_mapping ), 'orders' );
|
||||||
|
$non_cached_ids = array();
|
||||||
|
foreach ( $order_ids as $order_id ) {
|
||||||
|
if ( false === $cache_values[ $cache_keys_mapping[ $order_id ] ] ) {
|
||||||
|
$non_cached_ids[] = $order_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( empty( $non_cached_ids ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$order_ids = esc_sql( $non_cached_ids );
|
||||||
|
$order_ids_in = "'" . implode( "', '", $order_ids ) . "'";
|
||||||
|
$raw_meta_data_array = $wpdb->get_results(
|
||||||
|
// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
||||||
|
"SELECT post_id as object_id, meta_id, meta_key, meta_value
|
||||||
|
FROM {$wpdb->postmeta}
|
||||||
|
WHERE post_id IN ( $order_ids_in )
|
||||||
|
ORDER BY post_id"
|
||||||
|
// phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
||||||
|
);
|
||||||
|
$raw_meta_data_collection = array_reduce(
|
||||||
|
$raw_meta_data_array,
|
||||||
|
function ( $collection, $raw_meta_data ) {
|
||||||
|
if ( ! isset( $collection[ $raw_meta_data->object_id ] ) ) {
|
||||||
|
$collection[ $raw_meta_data->object_id ] = array();
|
||||||
|
}
|
||||||
|
$collection[ $raw_meta_data->object_id ][] = $raw_meta_data;
|
||||||
|
return $collection;
|
||||||
|
},
|
||||||
|
array()
|
||||||
|
);
|
||||||
|
WC_Order::prime_raw_meta_data_cache( $raw_meta_data_collection, 'orders' );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the order type of a given item which belongs to WC_Order.
|
* Return the order type of a given item which belongs to WC_Order.
|
||||||
*
|
*
|
||||||
|
|
|
@ -47,12 +47,15 @@ class WC_Order_Refund_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT im
|
||||||
*/
|
*/
|
||||||
public function delete( &$order, $args = array() ) {
|
public function delete( &$order, $args = array() ) {
|
||||||
$id = $order->get_id();
|
$id = $order->get_id();
|
||||||
|
$parent_order_id = $order->get_parent_id();
|
||||||
|
$refund_cache_key = WC_Cache_Helper::get_cache_prefix( 'orders' ) . 'refunds' . $parent_order_id;
|
||||||
|
|
||||||
if ( ! $id ) {
|
if ( ! $id ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wp_delete_post( $id );
|
wp_delete_post( $id );
|
||||||
|
wp_cache_delete( $refund_cache_key, 'orders' );
|
||||||
$order->set_id( 0 );
|
$order->set_id( 0 );
|
||||||
do_action( 'woocommerce_delete_order_refund', $id );
|
do_action( 'woocommerce_delete_order_refund', $id );
|
||||||
}
|
}
|
||||||
|
|
|
@ -283,6 +283,7 @@ abstract class WC_REST_CRUD_Controller extends WC_REST_Posts_Controller {
|
||||||
$args['post_parent__in'] = $request['parent'];
|
$args['post_parent__in'] = $request['parent'];
|
||||||
$args['post_parent__not_in'] = $request['parent_exclude'];
|
$args['post_parent__not_in'] = $request['parent_exclude'];
|
||||||
$args['s'] = $request['search'];
|
$args['s'] = $request['search'];
|
||||||
|
$args['fields'] = $this->get_fields_for_response( $request );
|
||||||
|
|
||||||
if ( 'date' === $args['orderby'] ) {
|
if ( 'date' === $args['orderby'] ) {
|
||||||
$args['orderby'] = 'date ID';
|
$args['orderby'] = 'date ID';
|
||||||
|
|
|
@ -2501,3 +2501,23 @@ function wc_is_running_from_async_action_scheduler() {
|
||||||
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||||||
return isset( $_REQUEST['action'] ) && 'as_async_request_queue_runner' === $_REQUEST['action'];
|
return isset( $_REQUEST['action'] ) && 'as_async_request_queue_runner' === $_REQUEST['action'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Polyfill for wp_cache_get_multiple for WP versions before 5.5.
|
||||||
|
*
|
||||||
|
* @param array $keys Array of keys to get from group.
|
||||||
|
* @param string $group Optional. Where the cache contents are grouped. Default empty.
|
||||||
|
* @param bool $force Optional. Whether to force an update of the local cache from the persistent
|
||||||
|
* cache. Default false.
|
||||||
|
* @return array|bool Array of values.
|
||||||
|
*/
|
||||||
|
function wc_cache_get_multiple( $keys, $group = '', $force = false ) {
|
||||||
|
if ( function_exists( 'wp_cache_get_multiple' ) ) {
|
||||||
|
return wp_cache_get_multiple( $keys, $group, $force );
|
||||||
|
}
|
||||||
|
$values = array();
|
||||||
|
foreach ( $keys as $key ) {
|
||||||
|
$values[ $key ] = wp_cache_get( $key, $group, $force );
|
||||||
|
}
|
||||||
|
return $values;
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "woocommerce",
|
"name": "woocommerce",
|
||||||
"title": "WooCommerce",
|
"title": "WooCommerce",
|
||||||
"version": "4.8.0",
|
"version": "4.9.0",
|
||||||
"homepage": "https://woocommerce.com/",
|
"homepage": "https://woocommerce.com/",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
|
@ -160,7 +160,7 @@ WooCommerce comes with some sample data you can use to see how products look; im
|
||||||
|
|
||||||
== Changelog ==
|
== Changelog ==
|
||||||
|
|
||||||
= 4.8.0 - 2020-12-xx =
|
= 4.9.0 - 2021-01-xx =
|
||||||
|
|
||||||
[See changelog for all versions](https://raw.githubusercontent.com/woocommerce/woocommerce/master/changelog.txt).
|
[See changelog for all versions](https://raw.githubusercontent.com/woocommerce/woocommerce/master/changelog.txt).
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class WC_Order_Data_Store_CPT_Test.
|
||||||
|
*/
|
||||||
|
class WC_Order_Data_Store_CPT_Test extends WC_Unit_Test_Case {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that refund cache are invalidated correctly when refund is deleted.
|
||||||
|
*/
|
||||||
|
public function test_refund_cache_invalidation() {
|
||||||
|
$order = WC_Helper_Order::create_order();
|
||||||
|
|
||||||
|
$refund = wc_create_refund(
|
||||||
|
array(
|
||||||
|
'order_id' => $order->get_id(),
|
||||||
|
'reason' => 'testing',
|
||||||
|
'amount' => 1,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertNotWPError( $refund );
|
||||||
|
|
||||||
|
// Prime cache.
|
||||||
|
$fetched_order = wc_get_orders(
|
||||||
|
array(
|
||||||
|
'post__in' => array( $order->get_id() ),
|
||||||
|
'type' => 'shop_order',
|
||||||
|
)
|
||||||
|
)[0];
|
||||||
|
|
||||||
|
$refund_cache_key = WC_Cache_Helper::get_cache_prefix( 'orders' ) . 'refunds' . $order->get_id();
|
||||||
|
$cached_refunds = wp_cache_get( $refund_cache_key, 'orders' );
|
||||||
|
|
||||||
|
$this->assertEquals( $cached_refunds[0]->get_id(), $fetched_order->get_refunds()[0]->get_id() );
|
||||||
|
|
||||||
|
$refund->delete( true );
|
||||||
|
|
||||||
|
// Cache should be cleared now.
|
||||||
|
$cached_refunds = wp_cache_get( $refund_cache_key, 'orders' );
|
||||||
|
$this->assertEquals( false, $cached_refunds );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -3,7 +3,7 @@
|
||||||
* Plugin Name: WooCommerce
|
* Plugin Name: WooCommerce
|
||||||
* Plugin URI: https://woocommerce.com/
|
* Plugin URI: https://woocommerce.com/
|
||||||
* Description: An eCommerce toolkit that helps you sell anything. Beautifully.
|
* Description: An eCommerce toolkit that helps you sell anything. Beautifully.
|
||||||
* Version: 4.8.0-dev
|
* Version: 4.9.0-dev
|
||||||
* Author: Automattic
|
* Author: Automattic
|
||||||
* Author URI: https://woocommerce.com
|
* Author URI: https://woocommerce.com
|
||||||
* Text Domain: woocommerce
|
* Text Domain: woocommerce
|
||||||
|
|
Loading…
Reference in New Issue