WCML_Product_Bundles

The WooCommerce Multilingual WCML Product Bundles class.

Defined (1)

The class is defined in the following location(s).

/compatibility/class-wcml-product-bundles.php  
  1. class WCML_Product_Bundles{ 
  2.  
  3. /** 
  4. * @var WPML_Element_Translation_Package 
  5. */ 
  6. public $tp; 
  7.  
  8. /** 
  9. * @var SitePress 
  10. */ 
  11. private $sitepress; 
  12.  
  13. /** 
  14. * @var woocommerce_wpml 
  15. */ 
  16. private $woocommerce_wpml; 
  17.  
  18. /** 
  19. * @var WCML_WC_Product_Bundles_Items 
  20. */ 
  21. private $product_bundles_items; 
  22.  
  23. /** 
  24. * WCML_Product_Bundles constructor. 
  25. */ 
  26. function __construct( &$sitepress, &$woocommerce_wpml, &$product_bundles_items ) { 
  27.  
  28. $this->sitepress = $sitepress; 
  29. $this->woocommerce_wpml = $woocommerce_wpml; 
  30. $this->product_bundles_items = $product_bundles_items; 
  31.  
  32. add_action( 'woocommerce_get_cart_item_from_session', array( $this, 'resync_bundle' ), 5, 3 ); 
  33. add_filter( 'woocommerce_cart_loaded_from_session', array( $this, 'resync_bundle_clean' ), 10 ); 
  34.  
  35. if( is_admin() ) { 
  36. $this->tp = new WPML_Element_Translation_Package(); 
  37.  
  38. add_filter( 'wpml_tm_translation_job_data', array( $this, 'append_bundle_data_translation_package' ), 10, 2 ); 
  39. add_action( 'wpml_translation_job_saved', array( $this, 'save_bundle_data_translation' ), 10, 3 ); 
  40.  
  41. add_action( 'wcml_gui_additional_box_html', array( $this, 'custom_box_html' ), 10, 3 ); 
  42. add_filter( 'wcml_gui_additional_box_data', array( $this, 'custom_box_html_data' ), 10, 4 ); 
  43.  
  44. add_action( 'wcml_after_duplicate_product_post_meta', array( $this, 'sync_bundled_ids' ), 10, 2 ); 
  45. add_action( 'wcml_update_extra_fields', array( $this, 'bundle_update' ), 10, 4 ); 
  46.  
  47. add_action( 'wp_insert_post', array( $this, 'sync_product_bundle_meta_with_translations' ), 10 ); 
  48.  
  49.  
  50. // product bundle using separate custom fields for prices 
  51. if( wcml_is_multi_currency_on() ) { 
  52. add_filter( 'wcml_price_custom_fields_filtered', array( $this, 'get_price_custom_fields' ) ); 
  53.  
  54.  
  55. private function get_product_bundle_data( $bundle_id ) { 
  56. $product_bundle_data = array(); 
  57.  
  58. $bundle_items = $this->product_bundles_items->get_items( $bundle_id ); 
  59. foreach( $bundle_items as $key => $bundle_item ) { 
  60. $product_bundle_data[ $bundle_item->item_id ] = $this->product_bundles_items->get_item_data( $bundle_item ); 
  61.  
  62. return $product_bundle_data; 
  63.  
  64. private function save_product_bundle_data( $bundle_id, $product_bundle_data ) { 
  65.  
  66. $bundle_items = $this->product_bundles_items->get_items( $bundle_id ); 
  67.  
  68. foreach( $bundle_items as $item_id => $bundle_item ) { 
  69. $bundled_item_data = $this->product_bundles_items->get_item_data_object( $item_id ); 
  70.  
  71. foreach( $product_bundle_data[ $item_id ] as $key => $value ) { 
  72. $this->product_bundles_items->update_item_meta( $bundled_item_data, $key, $value ); 
  73. $this->product_bundles_items->save_item_meta( $bundled_item_data ); 
  74.  
  75.  
  76. private function sync_product_bundle_meta( $bundle_id, $translated_bundle_id ) { 
  77.  
  78. $bundle_items = $this->product_bundles_items->get_items( $bundle_id ); 
  79. $fields_to_sync = array( 
  80. 'optional',  
  81. 'stock_status',  
  82. 'max_stock',  
  83. 'quantity_min',  
  84. 'quantity_max',  
  85. 'shipped_individually',  
  86. 'priced_individually',  
  87. 'single_product_visibility',  
  88. 'cart_visibility',  
  89. 'order_visibility',  
  90. 'single_product_price_visibility',  
  91. 'cart_price_visibility',  
  92. 'order_price_visibility' 
  93. ); 
  94.  
  95. $target_lang = $this->sitepress->get_language_for_element( $translated_bundle_id, 'post_product' ); 
  96. $translated_item_ids = array(); 
  97. foreach( $bundle_items as $item_id => $bundle_item ) { 
  98.  
  99. $item_meta = $this->product_bundles_items->get_item_data( $bundle_item ); 
  100. $translated_product_id = apply_filters( 'translate_object_id', $item_meta['product_id'], get_post_type( $item_meta['product_id'] ), false, $target_lang ); 
  101.  
  102. if( $translated_product_id ) { 
  103. $translated_item_id = $this->get_item_id_for_product_id( $translated_product_id, $translated_bundle_id ); 
  104. $translated_item_ids[] = $translated_item_id; 
  105.  
  106. $translated_item = $this->product_bundles_items->get_item_data_object( $translated_item_id ); 
  107. foreach( $fields_to_sync as $key ) { 
  108. $this->product_bundles_items->update_item_meta( $translated_item, $key, $item_meta[$key] ); 
  109. $this->product_bundles_items->save_item_meta( $translated_item ); 
  110.  
  111.  
  112.  
  113. // Delete removed items 
  114. $translated_bundle_items = $this->product_bundles_items->get_items( $translated_bundle_id ); 
  115. foreach ( $translated_bundle_items as $item_id => $bundle_item ) { 
  116. if ( ! in_array( $item_id, $translated_item_ids ) ) { 
  117. $bundled_item_data = $this->product_bundles_items->get_item_data_object( $item_id ); 
  118. $bundled_item_data->delete(); 
  119.  
  120.  
  121. public function sync_product_bundle_meta_with_translations( $bundle_id ) { 
  122.  
  123. if ( WooCommerce_Functions_Wrapper::get_product_type( $bundle_id ) === 'bundle' ) { 
  124.  
  125. $trid = $this->sitepress->get_element_trid( $bundle_id, 'post_product' ); 
  126. $translations = $this->sitepress->get_element_translations( $trid, 'post_product' ); 
  127.  
  128. foreach ( $translations as $language => $translation ) { 
  129. if ( $translation->original ) { 
  130. $original_bundle_id = $translation->element_id; 
  131. break; 
  132.  
  133.  
  134. foreach ( $translations as $language => $translation ) { 
  135. if ( $translation->element_id !== $original_bundle_id ) { 
  136. $this->sync_product_bundle_meta( $original_bundle_id, $translation->element_id ); 
  137.  
  138.  
  139.  
  140. private function get_product_id_for_item_id( $item_id ) { 
  141. global $wpdb; 
  142. return $wpdb->get_var( $wpdb->prepare( 
  143. "SELECT product_id FROM {$wpdb->prefix}woocommerce_bundled_items WHERE bundled_item_id=%d", $item_id) ); 
  144.  
  145. private function get_item_id_for_product_id( $product_id, $bundle_id ) { 
  146. global $wpdb; 
  147. return $wpdb->get_var( $wpdb->prepare( 
  148. "SELECT bundled_item_id FROM {$wpdb->prefix}woocommerce_bundled_items WHERE product_id=%d AND bundle_id=%d",  
  149. $product_id, $bundle_id 
  150. ) ); 
  151.  
  152. // Add Bundles Box to WCML Translation GUI 
  153. public function custom_box_html( $obj, $bundle_id, $data ) { 
  154.  
  155. $bundle_items = $this->product_bundles_items->get_items( $bundle_id ); 
  156.  
  157. if( empty( $bundle_items ) ) { 
  158. return false; 
  159.  
  160. $bundles_section = new WPML_Editor_UI_Field_Section( __( 'Product Bundles', 'woocommerce-multilingual' ) ); 
  161.  
  162. end( $bundle_items ); 
  163. $last_item_id = key( $bundle_items ); 
  164. $divider = true; 
  165. $flag = false; 
  166.  
  167. foreach ( $bundle_items as $item_id => $bundle_item ) { 
  168.  
  169. $translated_product = apply_filters( 'translate_object_id', $bundle_item->product_id, get_post_type( $bundle_item->product_id ), false, $obj->get_target_language() ); 
  170. if( !is_null($translated_product)) { 
  171.  
  172. $add_group = false; 
  173. if( $item_id == $last_item_id ) { 
  174. $divider = false; 
  175.  
  176. $bundle_item_data = $this->product_bundles_items->get_item_data( $bundle_item ); 
  177.  
  178. $group = new WPML_Editor_UI_Field_Group( get_the_title( $bundle_item->product_id ), $divider ); 
  179.  
  180. if( $bundle_item_data[ 'override_title' ] == 'yes' ) { 
  181. $bundle_field = new WPML_Editor_UI_Single_Line_Field( 
  182. 'bundle_' . $bundle_item->product_id . '_title',  
  183. __( 'Name', 'woocommerce-multilingual' ),  
  184. $data,  
  185. false 
  186. ); 
  187. $group->add_field( $bundle_field ); 
  188. $add_group = true; 
  189.  
  190. if( $bundle_item_data[ 'override_description' ] == 'yes' ) { 
  191. $bundle_field = new WPML_Editor_UI_Single_Line_Field( 
  192. 'bundle_'. $bundle_item->product_id . '_desc' ,  
  193. __( 'Description', 'woocommerce-multilingual' ),  
  194. $data,  
  195. false 
  196. ); 
  197. $group->add_field( $bundle_field ); 
  198. $add_group = true; 
  199.  
  200. if( $add_group ) { 
  201. $bundles_section->add_field( $group ); 
  202. $flag = true; 
  203.  
  204.  
  205.  
  206. if( $flag ) { 
  207. $obj->add_field( $bundles_section ); 
  208.  
  209.  
  210. public function custom_box_html_data( $data, $bundle_id, $translation, $lang ) { 
  211.  
  212. $bundle_data = $this->get_product_bundle_data( $bundle_id ); 
  213.  
  214. if( $translation ) { 
  215. $translated_bundle_id = $translation->ID; 
  216. $translated_bundle_data = $this->get_product_bundle_data( $translated_bundle_id ); 
  217.  
  218. if( empty( $bundle_data ) || $bundle_data == false ) { 
  219. return $data; 
  220.  
  221. $product_bundles = array_keys( $bundle_data ); 
  222.  
  223. foreach ( $product_bundles as $item_id ) { 
  224.  
  225. $product_id = $this->get_product_id_for_item_id( $item_id ); 
  226.  
  227. $translated_product_id = apply_filters( 'translate_object_id', $product_id, get_post_type( $product_id ), false, $lang ); 
  228. if( $translation ) { 
  229. $translated_item_id = $this->get_item_id_for_product_id( $translated_product_id, $translated_bundle_id ); 
  230.  
  231. if( $bundle_data[ $item_id ][ 'override_title' ] == 'yes' ) { 
  232. $data[ 'bundle_'.$product_id.'_title' ] = array( 'original' => $bundle_data[ $item_id ][ 'title' ] ); 
  233. if( $translation && isset( $translated_bundle_data[ $translated_item_id ][ 'override_title' ] ) ) { 
  234. $data[ 'bundle_'.$product_id.'_title' ][ 'translation' ] = $translated_bundle_data[ $translated_item_id ][ 'title' ]; 
  235. }else{ 
  236. $data[ 'bundle_'.$product_id.'_title' ][ 'translation' ] = ''; 
  237.  
  238. if( $bundle_data[ $item_id ][ 'override_description' ] == 'yes' ) { 
  239. $data[ 'bundle_'.$product_id.'_desc' ] = array( 'original' => $bundle_data[ $item_id ][ 'description' ] ); 
  240. if( $translation && isset( $translated_bundle_data[ $translated_item_id ][ 'override_description' ] ) ) { 
  241. $data[ 'bundle_'.$product_id.'_desc' ][ 'translation' ] = $translated_bundle_data[ $translated_item_id ][ 'description' ]; 
  242. }else{ 
  243. $data[ 'bundle_'.$product_id.'_desc' ][ 'translation' ] = ''; 
  244. return $data; 
  245.  
  246. public function append_bundle_data_translation_package( $package, $post ) { 
  247.  
  248. if( $post->post_type == 'product' ) { 
  249.  
  250. $bundle_data = $this->get_product_bundle_data( $post->ID ); 
  251.  
  252. if( $bundle_data ) { 
  253.  
  254. $fields = array( 'title', 'description' ); 
  255.  
  256. foreach( $bundle_data as $item_id => $product_data ) { 
  257.  
  258. $product_id = $this->get_product_id_for_item_id( $item_id ); 
  259. foreach( $fields as $field ) { 
  260. if ( $product_data[ 'override_' . $field ] == 'yes' && !empty( $product_data[ $field ] ) ) { 
  261. $package[ 'contents' ][ 'product_bundles:' . $product_id . ':' . $field ] = array( 
  262. 'translate' => 1,  
  263. 'data' => $this->tp->encode_field_data( $product_data[ $field ], 'base64' ),  
  264. 'format' => 'base64' 
  265. ); 
  266.  
  267. return $package; 
  268.  
  269.  
  270. // Update Bundled products title and description after saving the translation 
  271. public function bundle_update( $bundle_id, $translated_bundle_id, $data, $lang ) { 
  272. global $wpdb; 
  273.  
  274. $bundle_data = $this->get_product_bundle_data( $bundle_id ); 
  275. $translated_bundle_data = $this->get_product_bundle_data( $translated_bundle_id ); 
  276.  
  277. if( empty( $bundle_data ) ) { 
  278. return; 
  279.  
  280. $translate_bundled_item_ids = $wpdb->get_col( $wpdb->prepare( 
  281. "SELECT product_id FROM {$wpdb->prefix}woocommerce_bundled_items WHERE bundle_id = %d", $translated_bundle_id )); 
  282.  
  283. foreach ( $bundle_data as $item_id => $bundle_item_data ) { 
  284.  
  285. $product_id = $this->get_product_id_for_item_id( $item_id ); 
  286. $translated_product_id = apply_filters( 'translate_object_id', $product_id, get_post_type( $product_id ), false, $lang ); 
  287.  
  288. if( $translated_product_id ) { 
  289.  
  290. if ( ! in_array( $translated_product_id, $translate_bundled_item_ids ) ) { 
  291.  
  292. $menu_order = $wpdb->get_var( $wpdb->prepare( "  
  293. SELECT menu_order FROM {$wpdb->prefix}woocommerce_bundled_items 
  294. WHERE bundle_id=%d AND product_id=%d 
  295. ", $bundle_id, $bundle_item_data['product_id'] ) ); 
  296.  
  297. $wpdb->insert( $wpdb->prefix . 'woocommerce_bundled_items',  
  298. array( 
  299. 'product_id' => $translated_product_id,  
  300. 'bundle_id' => $translated_bundle_id,  
  301. 'menu_order' => $menu_order,  
  302. ); 
  303.  
  304. $translated_item_id = $this->get_item_id_for_product_id( $translated_product_id, $translated_bundle_id ); 
  305.  
  306. //$this->product_bundles_items->copy_item_data( $item_id, $translated_item_id ); 
  307.  
  308. if ( isset( $data[ md5( 'bundle_' . $product_id . '_title' ) ] ) ) { 
  309. $translated_bundle_data[ $translated_item_id ]['title'] = $data[ md5( 'bundle_' . $product_id . '_title' ) ]; 
  310. $translated_bundle_data[ $translated_item_id ]['override_title'] = $bundle_item_data['override_title']; 
  311.  
  312. if ( isset( $data[ md5( 'bundle_' . $product_id . '_desc' ) ] ) ) { 
  313. $translated_bundle_data[ $translated_item_id ]['description'] = $data[ md5( 'bundle_' . $product_id . '_desc' ) ]; 
  314. $translated_bundle_data[ $translated_item_id ]['override_description'] = $bundle_item_data['override_description']; 
  315.  
  316.  
  317.  
  318. $this->save_product_bundle_data( $translated_bundle_id, $translated_bundle_data ); 
  319. $this->sync_product_bundle_meta( $bundle_id, $translated_bundle_id ); 
  320.  
  321. $this->sitepress->copy_custom_fields ( $bundle_id, $translated_bundle_id ); 
  322.  
  323. return $translated_bundle_data; 
  324.  
  325. // Sync product bundle data with translated values when the product is duplicated 
  326. public function sync_bundled_ids( $bundle_id, $translated_bundle_id ) { 
  327. global $wpdb; 
  328.  
  329. $bundle_data = $this->get_product_bundle_data( $bundle_id ); 
  330. if( $bundle_data ) { 
  331. $lang = $this->sitepress->get_language_for_element( $translated_bundle_id, 'post_product' ); 
  332. $translated_bundle_data = $this->get_product_bundle_data( $translated_bundle_id ); 
  333.  
  334. foreach( $bundle_data as $item_id => $product_data ) { 
  335.  
  336. $product_id = $this->get_product_id_for_item_id( $item_id ); 
  337. $translated_product_id = apply_filters( 'translate_object_id', $product_id, get_post_type( $product_id ), false, $lang ); 
  338.  
  339. if( $translated_product_id ) { 
  340.  
  341. $translated_item_id = $this->get_item_id_for_product_id( $translated_product_id, $translated_bundle_id ); 
  342. if( !$translated_item_id ) { 
  343. $menu_order = $wpdb->get_var( $wpdb->prepare( "  
  344. SELECT menu_order FROM {$wpdb->prefix}woocommerce_bundled_items 
  345. WHERE bundle_id=%d AND product_id=%d 
  346. ", $bundle_id, $product_id ) ); 
  347.  
  348. $wpdb->insert( $wpdb->prefix . 'woocommerce_bundled_items',  
  349. array( 
  350. 'product_id' => $translated_product_id,  
  351. 'bundle_id' => $translated_bundle_id,  
  352. 'menu_order' => $menu_order,  
  353. ); 
  354. $translated_item_id = $wpdb->insert_id; 
  355.  
  356. $translated_bundle_data[ $translated_item_id ] = $product_data; 
  357. $translated_bundle_data[ $translated_item_id ]['product_id'] = $translated_product_id; 
  358.  
  359. if( isset( $bundle_data[ 'title' ] ) ) { 
  360. if( $bundle_data[ 'override_title' ] != 'yes' ) { 
  361. $translated_bundle_data[ $translated_item_id ][ 'title' ] = get_the_title( $translated_product_id ); 
  362.  
  363. if( isset( $bundle_data[ 'title' ] ) ) { 
  364. if( $bundle_data[ 'override_description' ] != 'yes' ) { 
  365. $translated_bundle_data[ $translated_item_id ][ 'description' ] = get_the_title( $translated_product_id ); 
  366.  
  367. if( isset( $bundle_data[ 'filter_variations' ] ) && $bundle_data[ 'filter_variations' ] == 'yes' ) { 
  368. $allowed_var = $bundle_data[ 'allowed_variations' ]; 
  369. foreach( $allowed_var as $key => $var_id ) { 
  370. $translated_var_id = apply_filters( 'translate_object_id', $var_id, get_post_type( $var_id ), true, $lang ); 
  371. $translated_bundle_data[ $translated_item_id ][ 'allowed_variations' ][ $key ] = $translated_var_id; 
  372.  
  373.  
  374. if( isset( $bundle_data[ 'bundle_defaults' ] ) && !empty( $bundle_data[ 'bundle_defaults' ] ) ) { 
  375. foreach( $bundle_data[ 'bundle_defaults' ] as $tax => $term_slug ) { 
  376.  
  377. $term_id = $this->woocommerce_wpml->terms->wcml_get_term_id_by_slug( $tax, $term_slug ); 
  378. if( $term_id ) { 
  379. // Global Attribute 
  380. $tr_def_id = apply_filters( 'translate_object_id', $term_id, $tax, true, $lang ); 
  381. $tr_term = $this->woocommerce_wpml->terms->wcml_get_term_by_id( $tr_def_id, $tax ); 
  382. $translated_bundle_data[ $translated_item_id ][ 'bundle_defaults' ][ $tax ] = $tr_term->slug; 
  383. }else{ 
  384. // Custom Attribute 
  385. $args = array( 
  386. 'post_type' => 'product_variation',  
  387. 'meta_key' => 'attribute_'.$tax,  
  388. 'meta_value' => $term_slug,  
  389. 'meta_compare' => '=' 
  390. ); 
  391. $variationloop = new WP_Query( $args ); 
  392. while ( $variationloop->have_posts() ) : $variationloop->the_post(); 
  393. $tr_var_id = apply_filters( 'translate_object_id', get_the_ID(), 'product_variation', true, $lang ); 
  394. $tr_meta = get_post_meta( $tr_var_id, 'attribute_'.$tax , true ); 
  395. $translated_bundle_data[ $translated_item_id ][ 'bundle_defaults' ][ $tax ] = $tr_meta; 
  396. endwhile; 
  397.  
  398.  
  399.  
  400.  
  401. $this->save_product_bundle_data( $translated_bundle_id, $translated_bundle_data ); 
  402.  
  403. return $translated_bundle_data; 
  404.  
  405.  
  406. public function resync_bundle( $cart_item, $session_values, $cart_item_key ) { 
  407.  
  408. if ( isset( $cart_item[ 'bundled_items' ] ) && $cart_item[ 'data' ]->product_type === 'bundle' ) { 
  409. $current_bundle_id = apply_filters( 'translate_object_id', $cart_item[ 'product_id' ], 'product', true ); 
  410. if ( $cart_item[ 'product_id' ] != $current_bundle_id ) { 
  411. $old_bundled_item_ids = array_keys( $cart_item[ 'data' ]->bundle_data ); 
  412. $cart_item[ 'data' ] = wc_get_product( $current_bundle_id ); 
  413. if( isset($cart_item[ 'data' ]->bundle_data) && is_array( $cart_item[ 'data' ]->bundle_data ) ) { 
  414. $new_bundled_item_ids = array_keys( $cart_item[ 'data' ]->bundle_data ); 
  415. $remapped_bundled_item_ids = array(); 
  416. foreach ( $old_bundled_item_ids as $old_item_id_index => $old_item_id ) { 
  417. $remapped_bundled_item_ids[ $old_item_id ] = $new_bundled_item_ids[ $old_item_id_index ]; 
  418. $cart_item[ 'remapped_bundled_item_ids' ] = $remapped_bundled_item_ids; 
  419. if ( isset( $cart_item[ 'stamp' ] ) ) { 
  420. $new_stamp = array(); 
  421. foreach ( $cart_item[ 'stamp' ] as $bundled_item_id => $stamp_data ) { 
  422. $new_stamp[ $remapped_bundled_item_ids[ $bundled_item_id ] ] = $stamp_data; 
  423. $cart_item[ 'stamp' ] = $new_stamp; 
  424. if ( isset( $cart_item[ 'bundled_by' ] ) && isset( WC()->cart->cart_contents[ $cart_item[ 'bundled_by' ] ] ) ) { 
  425. $bundle_cart_item = WC()->cart->cart_contents[ $cart_item[ 'bundled_by' ] ]; 
  426. if ( 
  427. isset( $bundle_cart_item[ 'remapped_bundled_item_ids' ] ) && 
  428. isset( $cart_item[ 'bundled_item_id' ] ) && 
  429. isset( $bundle_cart_item[ 'remapped_bundled_item_ids' ][ $cart_item[ 'bundled_item_id' ] ] ) 
  430. ) { 
  431. $old_id = $cart_item[ 'bundled_item_id' ]; 
  432. $remapped_bundled_item_ids = $bundle_cart_item[ 'remapped_bundled_item_ids' ]; 
  433. $cart_item[ 'bundled_item_id' ] = $remapped_bundled_item_ids[ $cart_item[ 'bundled_item_id' ] ]; 
  434. if ( isset( $cart_item[ 'stamp' ] ) ) { 
  435. $new_stamp = array(); 
  436. foreach ( $cart_item[ 'stamp' ] as $bundled_item_id => $stamp_data ) { 
  437. $new_stamp[ $remapped_bundled_item_ids[ $bundled_item_id ] ] = $stamp_data; 
  438. $cart_item[ 'stamp' ] = $new_stamp; 
  439.  
  440. return $cart_item; 
  441.  
  442. public function resync_bundle_clean( $cart ) { 
  443. foreach ( $cart->cart_contents as $cart_item_key => $cart_item ) { 
  444. if ( isset( $cart_item[ 'bundled_items' ] ) && WooCommerce_Functions_Wrapper::get_product_type( $cart_item[ 'product_id' ] ) === 'bundle' ) { 
  445. if ( isset( $cart_item[ 'remapped_bundled_item_ids' ] ) ) { 
  446. unset( WC()->cart->cart_contents[ $cart_item_key ][ 'remapped_bundled_item_ids' ] ); 
  447.  
  448. public function save_bundle_data_translation( $translated_bundle_id, $data, $job ) { 
  449.  
  450. remove_action( 'wcml_after_duplicate_product_post_meta', array( $this, 'sync_bundled_ids' ), 10, 2 ); 
  451.  
  452. $translated_bundle_data = $this->get_product_bundle_data( $translated_bundle_id ); 
  453.  
  454. $bundle_id =& $job->original_doc_id; 
  455.  
  456. $bundle_data = $this->get_product_bundle_data( $bundle_id ); 
  457.  
  458. foreach( $data as $value) { 
  459.  
  460. if( preg_match( '/product_bundles:([0-9]+):(.+)/', $value[ 'field_type' ], $matches ) ) { 
  461.  
  462. $product_id = $matches[1]; 
  463. $field = $matches[2]; 
  464.  
  465. $translated_product_id = apply_filters( 'translate_object_id', $product_id, get_post_type( $product_id ), false, $job->language_code ); 
  466. $translated_item_id = $this->get_item_id_for_product_id( $translated_product_id, $translated_bundle_id ); 
  467. if( empty( $translated_item_id ) ) { 
  468. $translated_item_id = $this->add_product_to_bundle( $translated_product_id, $translated_bundle_id, $bundle_id, $product_id ); 
  469.  
  470. $item_id = $this->get_item_id_for_product_id( $product_id, $bundle_id ); 
  471.  
  472. if( !isset( $translated_bundle_data[ $translated_item_id ] ) ) { 
  473. $translated_bundle_data[ $translated_item_id ] = array( 
  474. 'product_id' => $translated_product_id,  
  475. 'hide_thumbnail' => $bundle_data[ $item_id ][ 'hide_thumbnail' ],  
  476. 'override_title' => $bundle_data[ $item_id ][ 'override_title' ],  
  477. 'product_title' => '',  
  478. 'override_description' => $bundle_data[ $item_id ][ 'override_description' ],  
  479. 'product_description' => '',  
  480. 'optional' => $bundle_data[ $item_id ][ 'optional' ],  
  481. 'bundle_quantity' => $bundle_data[ $item_id ][ 'bundle_quantity' ],  
  482. 'bundle_quantity_max' => $bundle_data[ $item_id ][ 'bundle_quantity_max' ],  
  483. 'bundle_discount' => $bundle_data[ $item_id ][ 'bundle_discount' ],  
  484. 'single_product_visibility' => $bundle_data[ $item_id ][ 'single_product_visibility' ],  
  485. 'cart_visibility' => $bundle_data[ $item_id ][ 'cart_visibility' ],  
  486. 'order_visibility' => $bundle_data[ $item_id ][ 'order_visibility' ],  
  487. 'stock_status' => $bundle_data[ $item_id ][ 'stock_status' ],  
  488. 'max_stock' => $bundle_data[ $item_id ][ 'max_stock' ],  
  489. 'quantity_min' => $bundle_data[ $item_id ][ 'quantity_min' ],  
  490. 'quantity_max' => $bundle_data[ $item_id ][ 'quantity_max' ],  
  491. 'shipped_individually' => $bundle_data[ $item_id ][ 'shipped_individually' ],  
  492. 'priced_individually' => $bundle_data[ $item_id ][ 'priced_individually' ],  
  493. 'single_product_price_visibility' => $bundle_data[ $item_id ][ 'single_product_price_visibility' ],  
  494. 'cart_price_visibility' => $bundle_data[ $item_id ][ 'cart_price_visibility' ],  
  495. 'order_price_visibility' => $bundle_data[ $item_id ][ 'order_price_visibility' ] 
  496. ); 
  497.  
  498. $translated_bundle_data[ $translated_item_id ][ $field ] = $value[ 'data' ]; 
  499.  
  500.  
  501. $this->save_product_bundle_data( $translated_bundle_id, $translated_bundle_data ); 
  502.  
  503. private function add_product_to_bundle( $product_id, $bundle_id, $original_bundle_id, $original_product_id ) { 
  504. global $wpdb; 
  505. $menu_order = $wpdb->get_var( $wpdb->prepare( "  
  506. SELECT menu_order FROM {$wpdb->prefix}woocommerce_bundled_items 
  507. WHERE bundle_id=%d AND product_id=%d 
  508. ", $original_bundle_id, $original_product_id ) ); 
  509.  
  510. $wpdb->insert( $wpdb->prefix . 'woocommerce_bundled_items',  
  511. array( 
  512. 'product_id' => $product_id,  
  513. 'bundle_id' => $bundle_id,  
  514. 'menu_order' => $menu_order,  
  515. ); 
  516.  
  517. return $wpdb->insert_id; 
  518.  
  519. /** 
  520. * @param array $custom_fields 
  521. * @return array 
  522. */ 
  523. public function get_price_custom_fields( $custom_fields ) { 
  524.  
  525. $custom_fields = array_merge( $custom_fields, array( 
  526. '_wc_pb_base_regular_price',  
  527. '_wc_pb_base_sale_price',  
  528. '_wc_pb_base_price',  
  529. '_wc_sw_max_price',  
  530. '_wc_sw_max_regular_price' 
  531. ) ); 
  532.  
  533. return $custom_fields;