PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3-beta
Jetpack – WP Security, Backup, Speed, & Growth v16.3-beta
16.3-beta 16.3-a.5 16.3-a.7 16.3-a.3 16.3-a.1 16.2 16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 All 507 releases
← All changes | jetpack_vendor/automattic/jetpack-sync/src/modules/class-woocommerce-analytics.php +78 -9 16.2-beta → 16.3-beta View file →
@@ -6,9 +6,9 @@
6 6 * order product/coupon/tax lookup tables) to WordPress.com.
7 7 *
8 8 * Sync module name: `woocommerce_analytics`. The name, the action names, and the
9 9 * payload shapes are consumed by the WPCOM receiving side and by consumer packages
10 - * (Premium Analytics, WooCommerce AI); treat them as a public contract.
10 + * (Premium Analytics, the standalone WooCommerce Analytics plugin); treat them as a public contract.
11 11 *
12 12 * This module is NOT registered by default. Consumers own its registration,
13 13 * WooCommerce runtime guard, full-sync policy, and any additional Sync data
14 14 * configuration. The module provides the minimum option and post meta requirements.
@@ -65,8 +65,18 @@
65 65 '_global_unique_id',
66 66 );
67 67
68 68 /**
69 + * WooCommerce Analytics' order class for each plain order class, which adds the report methods used here.
70 + *
71 + * @var string[]
72 + */
73 + private static $analytics_order_classes = array(
74 + 'WC_Order' => 'Automattic\WooCommerce\Admin\Overrides\Order',
75 + 'WC_Order_Refund' => 'Automattic\WooCommerce\Admin\Overrides\OrderRefund',
76 + );
77 +
78 + /**
69 79 * Constructor.
70 80 */
71 81 public function __construct() {
72 82 add_filter( 'jetpack_sync_options_whitelist', array( $this, 'add_woocommerce_analytics_options_whitelist' ), 10 );
@@ -210,9 +220,9 @@
210 220 if ( ! in_array( $object_type, $this->get_supported_object_types(), true ) ) {
211 221 return array();
212 222 }
213 223
214 - $orders = wc_get_orders(
224 + $orders = self::get_analytics_orders(
215 225 array(
216 226 'post__in' => $ids,
217 227 'post_status' => WooCommerce_HPOS_Orders::get_all_possible_order_status_keys(),
218 228 'limit' => -1,
@@ -512,14 +522,23 @@
512 522 * @param mixed $order The order ID or the WC_Order object.
513 523 * @return array The reports data.
514 524 */
515 525 protected function build_woocommerce_analytics_reports_data( $order ) {
526 + // Reload once here, or each getter below would read the order again.
527 + $report_order = $order;
528 + if ( $order instanceof WC_Abstract_Order ) {
529 + $analytics_order = self::get_analytics_order( $order );
530 + if ( $analytics_order ) {
531 + $report_order = $analytics_order;
532 + }
533 + }
534 +
516 535 $data_types = array(
517 - 'order_stats' => $this->get_order_stats_data( $order ),
518 - 'order_attribution_data' => $this->get_order_attribution_data( $order ),
519 - 'order_product_data' => $this->get_order_product_data( $order ),
520 - 'order_coupon_data' => $this->get_order_coupon_data( $order ),
521 - 'order_tax_data' => $this->get_order_tax_data( $order ),
536 + 'order_stats' => $this->get_order_stats_data( $report_order ),
537 + 'order_attribution_data' => $this->get_order_attribution_data( $report_order ),
538 + 'order_product_data' => $this->get_order_product_data( $report_order ),
539 + 'order_coupon_data' => $this->get_order_coupon_data( $report_order ),
540 + 'order_tax_data' => $this->get_order_tax_data( $report_order ),
522 541 );
523 542
524 543 $reports_data = array_filter( $data_types );
525 544
@@ -651,9 +670,10 @@
651 670 } else {
652 671 return false;
653 672 }
654 673
655 - // If the order does not exit, check if the stats item is present in the wc_order_stats table.
674 + // If the order does not exist or cannot have report methods, read its wc_order_stats row instead.
675 + $order = self::get_analytics_order( $order );
656 676 if ( ! $order ) {
657 677 $order_stats_data_from_db = $this->get_order_stats_data_from_db( $order_id );
658 678 return $order_stats_data_from_db;
659 679 }
@@ -815,8 +835,56 @@
815 835 return $wpdb->get_results( $query, ARRAY_A ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
816 836 }
817 837
818 838 /**
839 + * Get the order as WooCommerce Analytics' order class, which adds the report methods used here.
840 + *
841 + * WooCommerce swaps that class in only while Analytics is enabled, and an object cache can outlive the switch.
842 + *
843 + * @param WC_Abstract_Order|false $order The order object.
844 + * @return WC_Abstract_Order|false The order with report methods, or false if it cannot have them.
845 + */
846 + private static function get_analytics_order( $order ) {
847 + if ( ! $order || method_exists( $order, 'get_report_customer_id' ) ) {
848 + return $order;
849 + }
850 +
851 + // Mirrors the exact-class check in WooCommerce's order_class_name filters, which leave subclasses alone.
852 + $analytics_class = self::$analytics_order_classes[ get_class( $order ) ] ?? null;
853 + if ( null === $analytics_class || ! class_exists( $analytics_class ) ) {
854 + return false;
855 + }
856 +
857 + return new $analytics_class( $order->get_id() );
858 + }
859 +
860 + /**
861 + * Query orders, loading them as WooCommerce Analytics' order classes even while Analytics is disabled.
862 + *
863 + * @param array $query_args Arguments for wc_get_orders().
864 + * @return WC_Order[]|\stdClass What wc_get_orders() returns.
865 + */
866 + private static function get_analytics_orders( $query_args ) {
867 + $added_callbacks = array();
868 + foreach ( self::$analytics_order_classes as $analytics_class ) {
869 + $callback = array( $analytics_class, 'order_class_name' );
870 + // Only add, and later remove, what WooCommerce has not, or its own filter goes with it.
871 + if ( class_exists( $analytics_class ) && false === has_filter( 'woocommerce_order_class', $callback ) ) {
872 + add_filter( 'woocommerce_order_class', $callback, 10, 3 );
873 + $added_callbacks[] = $callback;
874 + }
875 + }
876 +
877 + try {
878 + return wc_get_orders( $query_args );
879 + } finally {
880 + foreach ( $added_callbacks as $callback ) {
881 + remove_filter( 'woocommerce_order_class', $callback, 10 );
882 + }
883 + }
884 + }
885 +
886 + /**
819 887 * Check if the COGS feature is enabled.
820 888 *
821 889 * @return bool True if the COGS feature is enabled, false otherwise.
822 890 */
@@ -839,9 +907,10 @@
839 907 } else {
840 908 return false;
841 909 }
842 910
843 - // If the order does not exist, check if product lookup data exists in the database.
911 + // If the order does not exist or cannot have report methods, read its lookup rows instead.
912 + $order = self::get_analytics_order( $order );
844 913 if ( ! $order ) {
845 914 return $this->get_order_product_data_from_db( $order_id );
846 915 }
847 916