Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Initial exploration of compatibility with WC HPOS #4038

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 33 additions & 7 deletions includes/classes/Feature/WooCommerce/Orders.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,21 @@ class Orders {
*/
protected $woocommerce;

/**
* Receive the OrdersHPOS object instance
*
* @var OrdersHPOS
*/
protected $orders_hpos;

/**
* Class constructor
*
* @param WooCommerce $woocommerce WooCommerce feature object instance
*/
public function __construct( WooCommerce $woocommerce ) {
$this->woocommerce = $woocommerce;
$this->orders_hpos = new OrdersHPOS( $this );
}

/**
Expand All @@ -46,6 +54,10 @@ public function setup() {
add_action( 'parse_query', [ $this, 'search_order' ], 11 );
add_action( 'pre_get_posts', [ $this, 'translate_args' ], 11, 1 );
add_filter( 'ep_admin_notices', [ $this, 'hpos_compatibility_notice' ] );

if ( $this->is_hpos_enabled() ) {
$this->orders_hpos->setup();
}
}

/**
Expand All @@ -61,6 +73,10 @@ public function tear_down() {
remove_action( 'parse_query', [ $this, 'maybe_hook_woocommerce_search_fields' ], 1 );
remove_action( 'parse_query', [ $this, 'search_order' ], 11 );
remove_action( 'pre_get_posts', [ $this, 'translate_args' ], 11 );

if ( $this->is_hpos_enabled() ) {
$this->orders_hpos->tear_down();
}
}

/**
Expand Down Expand Up @@ -359,13 +375,7 @@ public function hpos_compatibility_notice( array $notices ) : array {
return $notices;
}

if (
! class_exists( '\Automattic\WooCommerce\Utilities\OrderUtil' )
|| ! method_exists( '\Automattic\WooCommerce\Utilities\OrderUtil', 'custom_orders_table_usage_is_enabled' ) ) {
return $notices;
}

if ( ! \Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled() ) {
if ( ! $this->is_hpos_enabled() ) {
return $notices;
}

Expand Down Expand Up @@ -480,6 +490,22 @@ public function translate_args( $query ) {
$this->maybe_set_search_fields( $query );
}

/**
* Whether WooCommerce HPOS is enabled or not
*
* @since 5.3.0
* @return boolean Whether WooCommerce HPOS is enabled or not
*/
public function is_hpos_enabled() : bool {
if (
! class_exists( '\Automattic\WooCommerce\Utilities\OrderUtil' )
|| ! method_exists( '\Automattic\WooCommerce\Utilities\OrderUtil', 'custom_orders_table_usage_is_enabled' ) ) {
return false;
}

return \Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled();
}

/**
* Handle calls to OrdersAutosuggest methods
*
Expand Down
131 changes: 131 additions & 0 deletions includes/classes/Feature/WooCommerce/OrdersHPOS.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
<?php
/**
* WooCommerce HPOS compatibility layer
*
* @since 5.3.0
* @package elasticpress
*/

namespace ElasticPress\Feature\WooCommerce;

use ElasticPress\Indexables;

if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}

/**
* WooCommerce HPOS
*/
class OrdersHPOS {
/**
* Orders object instance
*
* @var Orders
*/
protected $orders;

/**
* Class constructor
*
* @param Orders $orders Orders object instance
*/
public function __construct( Orders $orders ) {
$this->orders = $orders;
}

/**
* Setup order HPOS related hooks
*/
public function setup() {
add_action( 'woocommerce_new_order', [ $this, 'sync_order' ] );
add_action( 'woocommerce_refund_created', [ $this, 'sync_order' ] );
add_action( 'woocommerce_update_order', [ $this, 'sync_order' ] );
add_filter( 'ep_post_sync_args_post_prepare_meta', [ $this, 'set_order_data' ], 10, 2 );
}

/**
* Unsetup order HPOS related hooks
*/
public function tear_down() {
remove_action( 'woocommerce_new_order', [ $this, 'sync_order' ], 10, 2 );
remove_action( 'woocommerce_refund_created', [ $this, 'sync_order' ], 10, 2 );
remove_action( 'woocommerce_update_order', [ $this, 'sync_order' ], 10, 2 );
remove_filter( 'ep_post_sync_args_post_prepare_meta', [ $this, 'set_order_data' ], 10, 2 );
}

/**
* Add orders to the sync queue
*
* @param int $order_id Order ID.
*/
public function sync_order( $order_id ) {
Indexables::factory()->get( 'post' )->sync_manager->add_to_queue( $order_id );
}

/**
* Add order data to ES document args
*
* @param array $post_args Post arguments
* @param int $post_id Post ID
* @return array
*/
public function set_order_data( $post_args, $post_id ) {
if ( \Automattic\WooCommerce\Internal\DataStores\Orders\DataSynchronizer::PLACEHOLDER_ORDER_POST_TYPE !== $post_args['post_type'] ) {
return $post_args;
}

/**
* Post Indexable instance.
*
* @var \ElasticPress\Indexable\Post\Post
*/
$post_indexable = Indexables::factory()->get( 'post' );
$order = wc_get_order( $post_id );
$order_class = get_class( $order );
$post_order = new $order_class();

$post_args['post_type'] = $order->get_type();
$post_args['post_status'] = $order->get_status( 'edit' );
$post_args['post_parent'] = $order->get_changes()['parent_id'] ?? $order->get_data()['parent_id'] ?? 0;
$post_args['post_date'] = gmdate( 'Y-m-d H:i:s', $order->get_date_created( 'edit' )->getOffsetTimestamp() );
$post_args['post_date_gmt'] = gmdate( 'Y-m-d H:i:s', $order->get_date_created( 'edit' )->getTimestamp() );
$post_args['edit_date'] = true;
$post_args['post_excerpt'] = method_exists( $order, 'get_customer_note' ) ? $order->get_customer_note() : '';

$post_order = new $order_class();
$post_order->set_id( $order->get_id() );
$post_order->set_props( $order->get_data() );

error_log( var_export( $post_order, true ) );

Check warning on line 100 in includes/classes/Feature/WooCommerce/OrdersHPOS.php

View workflow job for this annotation

GitHub Actions / PHP Lint

error_log() found. Debug code should not normally be used in production.

Check warning on line 100 in includes/classes/Feature/WooCommerce/OrdersHPOS.php

View workflow job for this annotation

GitHub Actions / PHP Lint

var_export() found. Debug code should not normally be used in production.

add_filter( 'ep_prepare_meta_data', [ $this, 'prepare_meta_data' ], 10, 2 );
$post_args['meta'] = $post_indexable->prepare_meta_types( $post_indexable->prepare_meta( $post_order ) );
remove_filter( 'ep_prepare_meta_data', [ $this, 'prepare_meta_data' ] );

return $post_args;
}

/**
* Format meta data
*
* @param array $order_meta Meta data
* @param WP_Post $order_post Order object
* @return array
*/
public function prepare_meta_data( $order_meta, $order_post ) {
$order = wc_get_order( $order_post->get_id() );

if ( is_null( $order->get_meta() ) ) {
return $order_meta;
}

foreach ( $order->get_meta_data() as $meta_data ) {
$order_meta[ $meta_data->key ] = ( is_object( $meta_data->value ) && '__PHP_Incomplete_Class' === get_class( $meta_data->value ) )
? maybe_serialize( $meta_data->value )
: $meta_data->value;
}

return $order_meta;
}
}
34 changes: 29 additions & 5 deletions tests/php/features/WooCommerce/TestWooCommerceOrders.php
Original file line number Diff line number Diff line change
Expand Up @@ -348,11 +348,7 @@ public function test_hpos_compatibility_notice() {
ElasticPress\Features::factory()->activate_feature( 'protected_content' );
$this->assertCount( 1, $this->orders->hpos_compatibility_notice( $notices ) );

$option_name = \Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController::CUSTOM_ORDERS_TABLE_USAGE_ENABLED_OPTION;
$change_value = function() {
return 'yes';
};
add_filter( 'pre_option_' . $option_name, $change_value );
$this->enable_hpos();

$new_notices = $this->orders->hpos_compatibility_notice( $notices );
$this->assertCount( 2, $new_notices );
Expand All @@ -370,4 +366,32 @@ public function test_hpos_compatibility_notice() {
$this->assertCount( 1, $new_notices );
$this->assertArrayNotHasKey( 'wc_orders_incompatible', $new_notices );
}

/**
* Test the `is_hpos_enabled` method
*
* @since 5.3.0
* @group woocommerce
* @group woocommerce-orders
*/
public function test_is_hpos_enabled() {
$this->assertFalse( $this->orders->is_hpos_enabled() );

$this->enable_hpos();

$this->assertTrue( $this->orders->is_hpos_enabled() );
}

/**
* Utilitary function to enable WooCommerce HPOS
*
* @since 5.3.0
*/
protected function enable_hpos() {
$option_name = \Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController::CUSTOM_ORDERS_TABLE_USAGE_ENABLED_OPTION;
$change_value = function() {
return 'yes';
};
add_filter( 'pre_option_' . $option_name, $change_value );
}
}
Loading