class.jetpack-sync-module-woocommerce.php 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. <?php
  2. require_once JETPACK__PLUGIN_DIR . '/sync/class.jetpack-sync-module.php';
  3. class Jetpack_Sync_Module_WooCommerce extends Jetpack_Sync_Module {
  4. private $order_item_meta_whitelist = array(
  5. // https://github.com/woocommerce/woocommerce/blob/master/includes/data-stores/class-wc-order-item-product-store.php#L20
  6. '_product_id',
  7. '_variation_id',
  8. '_qty',
  9. // Tax ones also included in below class
  10. // https://github.com/woocommerce/woocommerce/blob/master/includes/data-stores/class-wc-order-item-fee-data-store.php#L20
  11. '_tax_class',
  12. '_tax_status',
  13. '_line_subtotal',
  14. '_line_subtotal_tax',
  15. '_line_total',
  16. '_line_tax',
  17. '_line_tax_data',
  18. // https://github.com/woocommerce/woocommerce/blob/master/includes/data-stores/class-wc-order-item-shipping-data-store.php#L20
  19. 'method_id',
  20. 'cost',
  21. 'total_tax',
  22. 'taxes',
  23. // https://github.com/woocommerce/woocommerce/blob/master/includes/data-stores/class-wc-order-item-tax-data-store.php#L20
  24. 'rate_id',
  25. 'label',
  26. 'compound',
  27. 'tax_amount',
  28. 'shipping_tax_amount',
  29. // https://github.com/woocommerce/woocommerce/blob/master/includes/data-stores/class-wc-order-item-coupon-data-store.php
  30. 'discount_amount',
  31. 'discount_amount_tax',
  32. );
  33. private $order_item_table_name;
  34. public function __construct() {
  35. global $wpdb;
  36. $this->order_item_table_name = $wpdb->prefix . 'woocommerce_order_items';
  37. // options, constants and post meta whitelists
  38. add_filter( 'jetpack_sync_options_whitelist', array( $this, 'add_woocommerce_options_whitelist' ), 10 );
  39. add_filter( 'jetpack_sync_constants_whitelist', array( $this, 'add_woocommerce_constants_whitelist' ), 10 );
  40. add_filter( 'jetpack_sync_post_meta_whitelist', array( $this, 'add_woocommerce_post_meta_whitelist' ), 10 );
  41. add_filter( 'jetpack_sync_before_enqueue_woocommerce_new_order_item', array( $this, 'filter_order_item' ) );
  42. add_filter( 'jetpack_sync_before_enqueue_woocommerce_update_order_item', array( $this, 'filter_order_item' ) );
  43. }
  44. function name() {
  45. return "woocommerce";
  46. }
  47. public function init_listeners( $callable ) {
  48. // orders
  49. add_action( 'woocommerce_new_order', $callable, 10, 1 );
  50. add_action( 'woocommerce_order_status_changed', $callable, 10, 3 );
  51. add_action( 'woocommerce_payment_complete', $callable, 10, 1 );
  52. // order items
  53. add_action( 'woocommerce_new_order_item', $callable, 10, 4 );
  54. add_action( 'woocommerce_update_order_item', $callable, 10, 4 );
  55. // order item meta
  56. $this->init_listeners_for_meta_type( 'order_item', $callable );
  57. }
  58. public function init_full_sync_listeners( $callable ) {
  59. add_action( 'jetpack_full_sync_woocommerce_order_items', $callable ); // also sends post meta
  60. }
  61. public function get_full_sync_actions() {
  62. return array( 'jetpack_full_sync_woocommerce_order_items' );
  63. }
  64. public function init_before_send() {
  65. // full sync
  66. add_filter( 'jetpack_sync_before_send_jetpack_full_sync_woocommerce_order_items', array( $this, 'expand_order_item_ids' ) );
  67. }
  68. public function filter_order_item( $args ) {
  69. // Make sure we always have all the data - prior to WooCommerce 3.0 we only have the user supplied data in the second argument and not the full details
  70. $args[1] = $this->build_order_item( $args[0] );
  71. return $args;
  72. }
  73. public function expand_order_item_ids( $args ) {
  74. $order_item_ids = $args[0];
  75. global $wpdb;
  76. $order_item_ids_sql = implode( ', ', array_map( 'intval', $order_item_ids ) );
  77. $order_items = $wpdb->get_results(
  78. "SELECT * FROM $this->order_item_table_name WHERE order_item_id IN ( $order_item_ids_sql )"
  79. );
  80. return array(
  81. $order_items,
  82. $this->get_metadata( $order_item_ids, 'order_item', $this->order_item_meta_whitelist ),
  83. );
  84. }
  85. public function build_order_item( $order_item_id ) {
  86. global $wpdb;
  87. return $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $this->order_item_table_name WHERE order_item_id = %d", $order_item_id ) );
  88. }
  89. public function enqueue_full_sync_actions( $config, $max_items_to_enqueue, $state ) {
  90. global $wpdb;
  91. return $this->enqueue_all_ids_as_action( 'jetpack_full_sync_woocommerce_order_items', $this->order_item_table_name, 'order_item_id', $this->get_where_sql( $config ), $max_items_to_enqueue, $state );
  92. }
  93. public function estimate_full_sync_actions( $config ) {
  94. global $wpdb;
  95. $query = "SELECT count(*) FROM $this->order_item_table_name WHERE " . $this->get_where_sql( $config );
  96. $count = $wpdb->get_var( $query );
  97. return (int) ceil( $count / self::ARRAY_CHUNK_SIZE );
  98. }
  99. private function get_where_sql( $config ) {
  100. return '1=1';
  101. }
  102. public function add_woocommerce_options_whitelist( $list ) {
  103. return array_merge( $list, self::$wc_options_whitelist );
  104. }
  105. public function add_woocommerce_constants_whitelist( $list ) {
  106. return array_merge( $list, self::$wc_constants_whitelist );
  107. }
  108. public function add_woocommerce_post_meta_whitelist( $list ) {
  109. return array_merge( $list, self::$wc_post_meta_whitelist );
  110. }
  111. private static $wc_options_whitelist = array(
  112. 'woocommerce_currency',
  113. 'woocommerce_db_version',
  114. 'woocommerce_weight_unit',
  115. 'woocommerce_version',
  116. 'woocommerce_unforce_ssl_checkout',
  117. 'woocommerce_tax_total_display',
  118. 'woocommerce_tax_round_at_subtotal',
  119. 'woocommerce_tax_display_shop',
  120. 'woocommerce_tax_display_cart',
  121. 'woocommerce_prices_include_tax',
  122. 'woocommerce_price_thousand_sep',
  123. 'woocommerce_price_num_decimals',
  124. 'woocommerce_price_decimal_sep',
  125. 'woocommerce_notify_low_stock',
  126. 'woocommerce_notify_low_stock_amount',
  127. 'woocommerce_notify_no_stock',
  128. 'woocommerce_notify_no_stock_amount',
  129. 'woocommerce_manage_stock',
  130. 'woocommerce_force_ssl_checkout',
  131. 'woocommerce_hide_out_of_stock_items',
  132. 'woocommerce_file_download_method',
  133. 'woocommerce_enable_signup_and_login_from_checkout',
  134. 'woocommerce_enable_shipping_calc',
  135. 'woocommerce_enable_review_rating',
  136. 'woocommerce_enable_guest_checkout',
  137. 'woocommerce_enable_coupons',
  138. 'woocommerce_enable_checkout_login_reminder',
  139. 'woocommerce_enable_ajax_add_to_cart',
  140. 'woocommerce_dimension_unit',
  141. 'woocommerce_default_country',
  142. 'woocommerce_default_customer_address',
  143. 'woocommerce_currency_pos',
  144. 'woocommerce_api_enabled',
  145. 'woocommerce_allow_tracking',
  146. );
  147. private static $wc_constants_whitelist = array(
  148. //woocommerce options
  149. 'WC_PLUGIN_FILE',
  150. 'WC_ABSPATH',
  151. 'WC_PLUGIN_BASENAME',
  152. 'WC_VERSION',
  153. 'WOOCOMMERCE_VERSION',
  154. 'WC_ROUNDING_PRECISION',
  155. 'WC_DISCOUNT_ROUNDING_MODE',
  156. 'WC_TAX_ROUNDING_MODE',
  157. 'WC_DELIMITER',
  158. 'WC_LOG_DIR',
  159. 'WC_SESSION_CACHE_GROUP',
  160. 'WC_TEMPLATE_DEBUG_MODE',
  161. );
  162. private static $wc_post_meta_whitelist = array(
  163. //woocommerce products
  164. // https://github.com/woocommerce/woocommerce/blob/8ed6e7436ff87c2153ed30edd83c1ab8abbdd3e9/includes/data-stores/class-wc-product-data-store-cpt.php#L21
  165. '_visibility',
  166. '_sku',
  167. '_price',
  168. '_regular_price',
  169. '_sale_price',
  170. '_sale_price_dates_from',
  171. '_sale_price_dates_to',
  172. 'total_sales',
  173. '_tax_status',
  174. '_tax_class',
  175. '_manage_stock',
  176. '_backorders',
  177. '_sold_individually',
  178. '_weight',
  179. '_length',
  180. '_width',
  181. '_height',
  182. '_upsell_ids',
  183. '_crosssell_ids',
  184. '_purchase_note',
  185. '_default_attributes',
  186. '_product_attributes',
  187. '_virtual',
  188. '_downloadable',
  189. '_download_limit',
  190. '_download_expiry',
  191. '_featured',
  192. '_downloadable_files',
  193. '_wc_rating_count',
  194. '_wc_average_rating',
  195. '_wc_review_count',
  196. '_variation_description',
  197. '_thumbnail_id',
  198. '_file_paths',
  199. '_product_image_gallery',
  200. '_product_version',
  201. '_wp_old_slug',
  202. //woocommerce orders
  203. // https://github.com/woocommerce/woocommerce/blob/8ed6e7436ff87c2153ed30edd83c1ab8abbdd3e9/includes/data-stores/class-wc-order-data-store-cpt.php#L27
  204. '_order_key',
  205. '_order_currency',
  206. // '_billing_first_name', do not sync these as they contain personal data
  207. // '_billing_last_name',
  208. // '_billing_company',
  209. // '_billing_address_1',
  210. // '_billing_address_2',
  211. '_billing_city',
  212. '_billing_state',
  213. '_billing_postcode',
  214. '_billing_country',
  215. // '_billing_email', do not sync these as they contain personal data
  216. // '_billing_phone',
  217. // '_shipping_first_name',
  218. // '_shipping_last_name',
  219. // '_shipping_company',
  220. // '_shipping_address_1',
  221. // '_shipping_address_2',
  222. '_shipping_city',
  223. '_shipping_state',
  224. '_shipping_postcode',
  225. '_shipping_country',
  226. '_completed_date',
  227. '_paid_date',
  228. '_cart_discount',
  229. '_cart_discount_tax',
  230. '_order_shipping',
  231. '_order_shipping_tax',
  232. '_order_tax',
  233. '_order_total',
  234. '_payment_method',
  235. '_payment_method_title',
  236. // '_transaction_id', do not sync these as they contain personal data
  237. // '_customer_ip_address',
  238. // '_customer_user_agent',
  239. '_created_via',
  240. '_order_version',
  241. '_prices_include_tax',
  242. '_date_completed',
  243. '_date_paid',
  244. '_payment_tokens',
  245. '_billing_address_index',
  246. '_shipping_address_index',
  247. '_recorded_sales',
  248. '_recorded_coupon_usage_counts',
  249. // https://github.com/woocommerce/woocommerce/blob/8ed6e7436ff87c2153ed30edd83c1ab8abbdd3e9/includes/data-stores/class-wc-order-data-store-cpt.php#L539
  250. '_download_permissions_granted',
  251. // https://github.com/woocommerce/woocommerce/blob/8ed6e7436ff87c2153ed30edd83c1ab8abbdd3e9/includes/data-stores/class-wc-order-data-store-cpt.php#L594
  252. '_order_stock_reduced',
  253. //woocommerce order refunds
  254. // https://github.com/woocommerce/woocommerce/blob/b8a2815ae546c836467008739e7ff5150cb08e93/includes/data-stores/class-wc-order-refund-data-store-cpt.php#L20
  255. '_order_currency',
  256. '_refund_amount',
  257. '_refunded_by',
  258. '_refund_reason',
  259. '_order_shipping',
  260. '_order_shipping_tax',
  261. '_order_tax',
  262. '_order_total',
  263. '_order_version',
  264. '_prices_include_tax',
  265. '_payment_tokens',
  266. );
  267. }