PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3
Jetpack – WP Security, Backup, Speed, & Growth v16.3
16.3 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 All 508 releases
← All changes | jetpack_vendor/automattic/jetpack-premium-analytics/src/Sync/class-configuration.php +69 -117 16.2 → 16.3 View file →
@@ -1,12 +1,8 @@
1 1 <?php
2 2 /**
3 - * TEMPORARY: interim port for WOOA7S-1550 — remove when the shared sync-modules composer package lands.
3 + * Premium Analytics glue for the shared WooCommerce Analytics sync module.
4 4 *
5 - * Plain replacement for woocommerce-analytics' src/Internal/Jetpack/Sync/Configuration.php, invoked
6 - * from {@see \Automattic\Jetpack\PremiumAnalytics\Analytics::init()} since this package has no PHP-DI
7 - * container to wire it through like upstream. Omits upstream's connection bootstrap and admin-script enqueue.
8 - *
9 5 * @package automattic/jetpack-premium-analytics
10 6 */
11 7
12 8 namespace Automattic\Jetpack\PremiumAnalytics\Sync;
@@ -12,37 +8,44 @@
12 8 namespace Automattic\Jetpack\PremiumAnalytics\Sync;
13 9
14 10 use Automattic\Jetpack\Config;
15 11 use Automattic\Jetpack\Sync\Data_Settings;
16 -use Automattic\Jetpack\Sync\Modules as JetpackSyncModules;
17 12 use Automattic\Jetpack\Sync\Modules\Meta as Meta_Module;
18 13 use Automattic\Jetpack\Sync\Modules\Posts as Posts_Module;
19 14 use Automattic\Jetpack\Sync\Modules\Term_Relationships as Term_Relationships_Module;
20 15 use Automattic\Jetpack\Sync\Modules\Terms as Terms_Module;
16 +use Automattic\Jetpack\Sync\Modules\WooCommerce_Analytics as WooCommerce_Analytics_Module;
21 17
22 18 defined( 'ABSPATH' ) || exit;
23 19
24 20 /**
25 - * Registers the WooCommerce Analytics Jetpack Sync module and its supporting filters.
21 + * Opts in to the shared WooCommerce Analytics sync module and registers the
22 + * Premium Analytics-specific sync configuration.
26 23 */
27 24 class Configuration {
28 25
29 - use Utilities;
26 + /**
27 + * FQCN of the Analytics module shipped by the standalone WooCommerce Analytics plugin.
28 + *
29 + * Must track that plugin's class: if it drifts, both modules load under the same
30 + * name and every analytics event syncs twice. Moot once that plugin consumes the
31 + * shared module, since the class strings then match.
32 + *
33 + * @since 0.9.0
34 + * @var string
35 + */
36 + const ANALYTICS_PLUGIN_MODULE_FQCN = 'Automattic\\WooCommerce\\Analytics\\Internal\\Jetpack\\Sync\\Modules\\Analytics';
30 37
31 38 /**
32 - * List of post meta to add to Sync's post meta whitelist.
33 - * Any changes to these meta will be synced to WordPress.com.
39 + * Bookings post meta to add to Sync's post meta whitelist. Bookings are synced
40 + * via the Posts + Meta modules; there is no dedicated bookings sync module.
34 41 *
42 + * Product meta needed by analytics reports is whitelisted by the shared module.
43 + *
35 44 * @static
36 45 * @var array
37 46 */
38 47 private static $postmeta_to_sync = array(
39 - // Products.
40 - '_stock',
41 - '_stock_quantity',
42 - '_cogs_total_value',
43 - '_global_unique_id',
44 - // Bookings.
45 48 '_booking_parent_id',
46 49 '_booking_duplicate_of',
47 50 '_booking_product_id',
48 51 '_booking_resource_id',
@@ -58,18 +61,22 @@
58 61 '_booking_attendance_status',
59 62 );
60 63
61 64 /**
62 - * Entry point called from Analytics::init(). Schedules the Sync hookups on plugins_loaded;
63 - * the actual registration is a no-op unless WooCommerce is active (see {@see configure_sync()}).
65 + * Entry point called from Analytics::init(). Schedules the Sync hookups on
66 + * plugins_loaded; the actual registration is a no-op unless WooCommerce is active
67 + * (see {@see configure_sync()}).
64 68 *
69 + * Call it before plugins_loaded completes: the Config built in configure_sync() wires
70 + * Sync\Main::configure() from a plugins_loaded priority 2 handler that never fires later.
71 + *
65 72 * @return void
66 73 */
67 74 public static function register(): void {
68 75 $instance = new self();
69 76
70 - // Defer to plugins_loaded so the WooCommerce-active guard runs after every plugin loads; priority 1
71 - // also lets the Jetpack Config constructed below run its on_plugins_loaded (priority 2) handler in the same cycle.
77 + // plugins_loaded priority 1: every plugin has loaded for the WooCommerce guard, and the
78 + // Config constructed in configure_sync() still gets its priority 2 handler in this cycle.
72 79 if ( did_action( 'plugins_loaded' ) ) {
73 80 $instance->configure_sync();
74 81 } else {
75 82 add_action( 'plugins_loaded', array( $instance, 'configure_sync' ), 1 );
@@ -85,13 +92,11 @@
85 92 return class_exists( 'WooCommerce' ) || function_exists( 'WC' );
86 93 }
87 94
88 95 /**
89 - * Register the Jetpack Sync filters and ensure the Sync feature, when WooCommerce is active.
96 + * Register the Jetpack Sync filters and ensure the Sync feature when WooCommerce
97 + * is active.
90 98 *
91 - * No-op unless WooCommerce is active, since the module relies on WooCommerce runtime symbols
92 - * (WC_Order, the wc_order_stats table, OrderUtil, etc.).
93 - *
94 99 * @return void
95 100 */
96 101 public function configure_sync(): void {
97 102 if ( ! self::is_woocommerce_active() ) {
@@ -97,11 +102,11 @@
97 102 if ( ! self::is_woocommerce_active() ) {
98 103 return;
99 104 }
100 105
101 - add_filter( 'jetpack_sync_modules', array( $this, 'add_woocommerce_analytics_module' ) );
106 + // The shared module is registered through the Sync config below; this only drops a duplicate.
107 + add_filter( 'jetpack_sync_modules', array( $this, 'remove_duplicate_woocommerce_analytics_module' ), PHP_INT_MAX );
102 108 add_filter( 'jetpack_full_sync_config', array( $this, 'expand_full_sync_config' ) );
103 - add_filter( 'jetpack_sync_checksum_allowed_tables', array( $this, 'add_order_stats_to_checksum' ) );
104 109 add_filter( 'jetpack_sync_post_meta_whitelist', array( $this, 'add_meta_to_sync_post_meta_whitelist' ) );
105 110
106 111 ( new Config() )->ensure( 'sync', $this->get_jetpack_sync_config() );
107 112 }
@@ -106,43 +111,27 @@
106 111 ( new Config() )->ensure( 'sync', $this->get_jetpack_sync_config() );
107 112 }
108 113
109 114 /**
110 - * Add the WooCommerce Analytics module to the list of Jetpack Sync modules.
115 + * Jetpack Sync module configuration.
111 116 *
112 - * @param array $modules The current list of sync module class names.
113 - * @return array
114 - */
115 - public function add_woocommerce_analytics_module( $modules ) {
116 - if ( is_array( $modules ) && ! in_array( WooCommerce_Analytics_Module::class, $modules, true ) ) {
117 - $modules[] = WooCommerce_Analytics_Module::class;
118 - }
119 -
120 - return $modules;
121 - }
122 -
123 - /**
124 - * Jetpack Sync module configuration.
117 + * MUST_SYNC_DATA_SETTINGS is merged in because Data_Settings falls back to the full default
118 + * whitelist for any filter a consumer leaves out, which would widen standalone sites.
125 119 *
126 120 * @return array Jetpack Sync config array.
127 121 */
128 122 private function get_jetpack_sync_config(): array {
129 - $jetpack_sync_modules = array_keys(
130 - array_filter(
131 - array(
132 - WooCommerce_Analytics_Module::class => true,
133 - Meta_Module::class => true,
134 - Posts_Module::class => true,
135 - Terms_Module::class => true,
136 - Term_Relationships_Module::class => true,
137 - )
138 - )
139 - );
140 -
141 123 return array_merge_recursive(
142 124 Data_Settings::MUST_SYNC_DATA_SETTINGS,
143 125 array(
144 - 'jetpack_sync_modules' => $jetpack_sync_modules,
126 + 'jetpack_sync_modules' => array(
127 + WooCommerce_Analytics_Module::class,
128 + Meta_Module::class,
129 + Posts_Module::class,
130 + Terms_Module::class,
131 + Term_Relationships_Module::class,
132 + ),
133 + // Listed explicitly so the contract does not depend on which other Sync modules load.
145 134 'jetpack_sync_options_whitelist' => array(
146 135 'woocommerce_custom_orders_table_enabled', // Required for HPOS checksums.
147 136 'woocommerce_excluded_report_order_statuses', // Required for generating analytics reports.
148 137 'woocommerce_date_type', // Date used to determine the date range for analytics reports.
@@ -147,10 +136,10 @@
147 136 'woocommerce_excluded_report_order_statuses', // Required for generating analytics reports.
148 137 'woocommerce_date_type', // Date used to determine the date range for analytics reports.
149 138 ),
150 139 'jetpack_sync_constants_whitelist' => array(
151 - // Syncing this triggers WPCom to provision the WC Analytics tables (WOOA7S-1643).
152 - // WC_ANALYTICS_VERSION is omitted: only woocommerce-analytics defines it, so a PA-only store would sync null.
140 + // Syncing it makes WPCOM provision the WC Analytics tables (WOOA7S-1643). WC_ANALYTICS_VERSION
141 + // belongs to the standalone plugin and would only sync null on a PA-only store.
153 142 'JETPACK_PREMIUM_ANALYTICS__VERSION',
154 143 ),
155 144 )
156 145 );
@@ -156,19 +145,36 @@
156 145 );
157 146 }
158 147
159 148 /**
160 - * Expand full sync config with module required by WooCommerce Analytics if not already present.
149 + * Drop the standalone plugin's Analytics module in favor of the shared one.
161 150 *
162 - * @param array $config The current full sync configuration.
163 - * @return array The modified full sync configuration.
151 + * Sync dedups by class name only, so both would load and sync every event twice. The shared
152 + * module wins because the released standalone one syncs no lookup data, while the sync package
153 + * advertises the lookup checksum tables for any module of this name.
154 + *
155 + * Runs at PHP_INT_MAX because Data_Settings re-asserts its whole module list at priority 10.
156 + *
157 + * @param array|mixed $modules Current Sync module class names.
158 + * @return array|mixed Updated Sync module class names.
164 159 */
165 - public function expand_full_sync_config( array $config ): array {
166 - if ( ! $this->can_site_sync_orders() ) {
167 - return $config;
160 + public function remove_duplicate_woocommerce_analytics_module( $modules ) {
161 + // An emptied list is a kill switch (Jetpack's uninstaller uses one); leave it alone.
162 + if ( ! is_array( $modules ) || empty( $modules ) ) {
163 + return $modules;
168 164 }
169 165
170 - // Let's ensure Terms and Term_Relationships will always get synced before Posts during Full Sync.
166 + return array_values( array_diff( $modules, array( self::ANALYTICS_PLUGIN_MODULE_FQCN ) ) );
167 + }
168 +
169 + /**
170 + * Add the Analytics module to full sync, first in line.
171 + *
172 + * @param array $config Current full-sync configuration.
173 + * @return array Updated full-sync configuration.
174 + */
175 + public function expand_full_sync_config( array $config ): array {
176 + // Terms and term relationships must be synced before posts.
171 177 if ( isset( $config['posts'] ) ) {
172 178 unset( $config['posts'] );
173 179 $config += array( 'posts' => 1 );
174 180 }
@@ -180,63 +186,9 @@
180 186 return $config;
181 187 }
182 188
183 189 /**
184 - * Adds the order stats table to the checksum allowed tables.
185 - *
186 - * @param array $tables The current checksum allowed tables.
187 - * @return array The modified checksum allowed tables.
188 - */
189 - public function add_order_stats_to_checksum( array $tables ): array {
190 - if ( ! $this->can_site_sync_orders() ) {
191 - return $tables;
192 - }
193 -
194 - global $wpdb;
195 - $order_stats_checksum_table = array(
196 - 'wc_order_stats' => array(
197 - 'table' => "{$wpdb->prefix}wc_order_stats",
198 - 'range_field' => 'order_id',
199 - 'key_fields' => array( 'order_id' ),
200 - 'checksum_fields' => array( 'date_paid', 'date_completed', 'total_sales' ),
201 - 'checksum_text_fields' => array( 'status' ),
202 - 'is_table_enabled_callback' => function () {
203 - return false !== JetpackSyncModules::get_module( 'woocommerce_analytics' );
204 - },
205 - ),
206 - 'wc_order_product_lookup' => array(
207 - 'table' => "{$wpdb->prefix}wc_order_product_lookup",
208 - 'range_field' => 'order_id',
209 - 'key_fields' => array( 'order_id', 'order_item_id' ),
210 - 'checksum_fields' => array( 'product_id', 'variation_id', 'product_qty', 'product_net_revenue', 'date_created' ),
211 - 'is_table_enabled_callback' => function () {
212 - return false !== JetpackSyncModules::get_module( 'woocommerce_analytics' );
213 - },
214 - ),
215 - 'wc_order_coupon_lookup' => array(
216 - 'table' => "{$wpdb->prefix}wc_order_coupon_lookup",
217 - 'range_field' => 'order_id',
218 - 'key_fields' => array( 'order_id', 'coupon_id' ),
219 - 'checksum_fields' => array( 'discount_amount', 'date_created' ),
220 - 'is_table_enabled_callback' => function () {
221 - return false !== JetpackSyncModules::get_module( 'woocommerce_analytics' );
222 - },
223 - ),
224 - 'wc_order_tax_lookup' => array(
225 - 'table' => "{$wpdb->prefix}wc_order_tax_lookup",
226 - 'range_field' => 'order_id',
227 - 'key_fields' => array( 'order_id', 'tax_rate_id' ),
228 - 'checksum_fields' => array( 'order_tax', 'total_tax', 'shipping_tax', 'date_created' ),
229 - 'is_table_enabled_callback' => function () {
230 - return false !== JetpackSyncModules::get_module( 'woocommerce_analytics' );
231 - },
232 - ),
233 - );
234 - return array_merge( $tables, $order_stats_checksum_table );
235 - }
236 -
237 - /**
238 - * Add WC Analytics post meta to Sync's post meta whitelist.
190 + * Add Bookings post meta to Sync's post meta whitelist.
239 191 * Any changes to these meta will be synced to WordPress.com.
240 192 *
241 193 * @param array $whitelist Existing post meta whitelist.
242 194 * @return array Updated post meta whitelist.