WooCommerce Multilingual – run WooCommerce with WPML - Version 3.6.10

Version Description

  • Bug fix: Custom prices for variations were not saved when clicking the 'Save changes' button
  • Bug fix: Pagination was not working for a category having the term id equal to the id of the account page
  • Bug fix: 'Shop' was appearing two times in the breadcrumbs when using the shop base + category for a product url base
  • Bug fix: Fixed one issue with WooCommerce Bookings - adding two separate bookings to the cart showed as one item instead of two
  • Bug fix: The products menu order was not synced in some situations
  • Fixed a compatibility issue with the Peddlar theme
  • Fixed a styling issue on the custom prices section for product variations
  • Updates for the compatibility with WooCommerce Product Bundles from the plugin author
  • Bug fix: Sometimes it was not possible to enable the slug translation for a custom post when WooCommerce Multilingual was active
Download this release

Release Info

Developer mihaimihai
Plugin Icon 128x128 WooCommerce Multilingual – run WooCommerce with WPML
Version 3.6.10
Comparing to
See all releases

Code changes from version 3.6.9 to 3.6.10

assets/css/wcml-prices.css CHANGED
@@ -74,7 +74,6 @@
74
  }
75
  .wcml_custom_prices_manually_block_show,
76
  .wcml_custom_prices_manually_block_hide{
77
- display: none;
78
  clear: both;
79
  float: left;
80
  }
74
  }
75
  .wcml_custom_prices_manually_block_show,
76
  .wcml_custom_prices_manually_block_hide{
 
77
  clear: both;
78
  float: left;
79
  }
assets/js/lock_fields.js CHANGED
@@ -77,6 +77,7 @@ var wcml_lock_variation_fields = function(){
77
  jQuery('.woocommerce_variation>h3 select, #variable_product_options .toolbar select, .show_if_variation_manage_stock select').each(function(){
78
 
79
  jQuery(this).attr('disabled','disabled');
 
80
  jQuery(this).after(jQuery('.wcml_lock_img').clone().removeClass('wcml_lock_img').show());
81
  });
82
 
@@ -105,6 +106,7 @@ var wcml_lock_variation_fields = function(){
105
  for (i = 0; i < var_selectboxes.length; i++) {
106
  jQuery('select[name^="variable'+var_selectboxes[i]+'"]').each(function(){
107
  jQuery(this).attr('disabled','disabled');
 
108
  jQuery(this).after(jQuery('.wcml_lock_img').clone().removeClass('wcml_lock_img').show());
109
  });
110
  }
77
  jQuery('.woocommerce_variation>h3 select, #variable_product_options .toolbar select, .show_if_variation_manage_stock select').each(function(){
78
 
79
  jQuery(this).attr('disabled','disabled');
80
+ jQuery(this).parent().append('<input type="hidden" name="'+jQuery(this).attr('name')+'" value="'+jQuery(this).val()+'" />');
81
  jQuery(this).after(jQuery('.wcml_lock_img').clone().removeClass('wcml_lock_img').show());
82
  });
83
 
106
  for (i = 0; i < var_selectboxes.length; i++) {
107
  jQuery('select[name^="variable'+var_selectboxes[i]+'"]').each(function(){
108
  jQuery(this).attr('disabled','disabled');
109
+ jQuery(this).parent().append('<input type="hidden" name="'+jQuery(this).attr('name')+'" value="'+jQuery(this).val()+'" />');
110
  jQuery(this).after(jQuery('.wcml_lock_img').clone().removeClass('wcml_lock_img').show());
111
  });
112
  }
compatibility/wc_bookings.class.php CHANGED
@@ -57,6 +57,7 @@ class WCML_Bookings{
57
  }
58
 
59
  add_filter( 'parse_query', array( $this, 'booking_filters_query' ) );
 
60
 
61
  }
62
 
@@ -961,7 +962,7 @@ class WCML_Bookings{
961
 
962
  function filter_bundled_product_in_cart_contents( $cart_item, $key, $current_language ){
963
 
964
- if( $cart_item[ 'data' ] instanceof WC_Product_Booking ){
965
  global $woocommerce_wpml;
966
 
967
  $current_id = apply_filters( 'translate_object_id', $cart_item[ 'data' ]->id, 'product', true, $current_language );
@@ -1570,4 +1571,14 @@ class WCML_Bookings{
1570
  );
1571
  }
1572
  }
 
 
 
 
 
 
 
 
 
 
1573
  }
57
  }
58
 
59
  add_filter( 'parse_query', array( $this, 'booking_filters_query' ) );
60
+ add_filter('wcml_exception_duplicate_products_in_cart', array($this, 'check_on_bookable_product_in_cart'), 10, 2 );
61
 
62
  }
63
 
962
 
963
  function filter_bundled_product_in_cart_contents( $cart_item, $key, $current_language ){
964
 
965
+ if( $cart_item[ 'data' ] instanceof WC_Product_Booking && isset( $cart_item[ 'booking' ] ) ){
966
  global $woocommerce_wpml;
967
 
968
  $current_id = apply_filters( 'translate_object_id', $cart_item[ 'data' ]->id, 'product', true, $current_language );
1571
  );
1572
  }
1573
  }
1574
+
1575
+ function check_on_bookable_product_in_cart( $flag, $cart_item ){
1576
+
1577
+ if( $cart_item[ 'data' ] instanceof WC_Product_Booking ) {
1578
+ return true;
1579
+ }
1580
+
1581
+ return false;
1582
+
1583
+ }
1584
  }
compatibility/wc_product_bundles.class.php CHANGED
@@ -1,43 +1,32 @@
1
  <?php
2
-
3
  class WCML_Product_Bundles{
4
-
5
  function __construct(){
6
- add_action('wcml_gui_additional_box',array($this,'product_bundles_box'),10,3);
7
- add_action('wcml_after_duplicate_product_post_meta',array($this,'sync_bundled_ids'),10,3);
8
- add_action('wcml_extra_titles',array($this,'product_bundles_title'),10,1);
9
- add_action('wcml_update_extra_fields',array($this,'bundle_update'),10,2);
10
- add_filter('wcml_cart_contents', array($this, 'cart_bundle_update_lang_switch'), 10, 4);
11
- add_filter('wcml_update_cart_contents_lang_switch', array($this, 'cart_contents_bundle_update_lang_switch'), 10, 4);
12
- add_filter('wcml_filter_cart_item_data', array($this, 'filter_cart_item_data') );
13
- add_filter('wcml_check_on_duplicated_products_in_cart', array($this, 'removeduplicated_bundle_product_in_cart'), 10, 3 );
14
- add_filter('wcml_exception_duplicate_products_in_cart', array($this, 'check_on_bundle_product_in_cart'), 10, 2 );
15
  }
16
-
17
  // Sync Bundled product '_bundle_data' with translated values when the product is duplicated
18
  function sync_bundled_ids($original_product_id, $trnsl_product_id, $data = false){
19
  global $sitepress;
20
-
21
  $atts = maybe_unserialize(get_post_meta($original_product_id, '_bundle_data', true));
22
-
23
  if( $atts ){
24
  $lang = $sitepress->get_language_for_element($trnsl_product_id,'post_product');
25
  $tr_ids = array();
26
  $i = 2;
27
  foreach($atts as $id=>$bundle_data){
28
  $tr_id = apply_filters( 'translate_object_id',$id,get_post_type($id),true,$lang);
29
-
30
  if(isset($tr_bundle[$tr_id])){
31
  $bundle_key = $tr_id.'_'.$i;
32
  $i++;
33
  }else{
34
  $bundle_key = $tr_id;
35
  }
36
-
37
  $tr_bundle[$bundle_key] = $bundle_data;
38
-
39
  $tr_bundle[$bundle_key]['product_id'] = $tr_id;
40
-
41
  if(isset($bundle_data['product_title'])){
42
  if($bundle_data['override_title']=='yes'){
43
  $tr_bundle[$bundle_key]['product_title'] = '';
@@ -46,7 +35,6 @@ class WCML_Product_Bundles{
46
  $tr_bundle[$bundle_key]['product_title'] = $tr_title;
47
  }
48
  }
49
-
50
  if(isset($bundle_data['product_description'])){
51
  if($bundle_data['override_description']=='yes'){
52
  $tr_bundle[$bundle_key]['product_description'] = '';
@@ -56,7 +44,6 @@ class WCML_Product_Bundles{
56
  $tr_bundle[$bundle_key]['product_description'] = $tr_desc;
57
  }
58
  }
59
-
60
  if(isset($bundle_data['filter_variations']) && $bundle_data['filter_variations']=='yes'){
61
  $allowed_var = $bundle_data['allowed_variations'];
62
  foreach($allowed_var as $key=>$var_id){
@@ -64,13 +51,10 @@ class WCML_Product_Bundles{
64
  $tr_bundle[$bundle_key]['allowed_variations'][$key] = $tr_var_id;
65
  }
66
  }
67
-
68
  if(isset($bundle_data['bundle_defaults']) && !empty($bundle_data['bundle_defaults'])){
69
  foreach($bundle_data['bundle_defaults'] as $tax=>$term_slug){
70
-
71
  global $woocommerce_wpml;
72
  $term_id = $woocommerce_wpml->products->wcml_get_term_id_by_slug( $tax, $term_slug );
73
-
74
  if( $term_id ){
75
  // Global Attribute
76
  $tr_def_id = apply_filters( 'translate_object_id',$term_id,$tax,true,$lang);
@@ -86,25 +70,17 @@ class WCML_Product_Bundles{
86
  $tr_bundle[$bundle_key]['bundle_defaults'][$tax] = $tr_meta;
87
  endwhile;
88
  }
89
-
90
  }
91
  }
92
-
93
-
94
  }
95
-
96
  update_post_meta($trnsl_product_id,'_bundle_data',$tr_bundle);
97
  }
98
-
99
  }
100
-
101
  // Update Bundled products title and descritpion after saving the translation
102
  function bundle_update($tr_id, $data){
103
-
104
  global $sitepress;
105
  $tr_bundle_data = array();
106
- $tr_bundle_data = maybe_unserialize(get_post_meta($tr_id,'_bundle_data', true));
107
-
108
  if(!empty($data['bundles'])){
109
  foreach($data['bundles'] as $bundle_id => $bundle_data){
110
  if(isset($tr_bundle_data[$bundle_id])){
@@ -112,12 +88,10 @@ class WCML_Product_Bundles{
112
  $tr_bundle_data[$bundle_id]['product_description'] = $bundle_data['bundle_desc'];
113
  }
114
  }
115
- update_post_meta( $tr_id, '_bundle_data', $tr_bundle_data );
116
  $tr_bundle_data = array();
117
  }
118
-
119
  }
120
-
121
  // Add 'Product Bundles' title to the WCML Product GUI if the current product is a bundled product
122
  function product_bundles_title($product_id){
123
  $bundle_data = maybe_unserialize(get_post_meta($product_id,'_bundle_data', true));
@@ -125,17 +99,13 @@ class WCML_Product_Bundles{
125
  <th scope="col"><?php _e('Product Bundles', 'wcml_product_bundles'); ?></th>
126
  <?php }
127
  }
128
-
129
  // Add Bundles Box to WCML Translation GUI
130
  function product_bundles_box($product_id,$lang, $is_duplicate_product = false ) {
131
  global $sitepress, $woocommerce_wpml;
132
  $isbundle = true;
133
  $translated = true;
134
  $template_data = array();
135
-
136
  $default_language = $woocommerce_wpml->products->get_original_product_language( $product_id );
137
-
138
-
139
  if($default_language != $lang){
140
  $tr_product_id = apply_filters( 'translate_object_id',$product_id, 'product', true, $lang);
141
  if($tr_product_id == $product_id){
@@ -144,23 +114,18 @@ class WCML_Product_Bundles{
144
  $product_id = $tr_product_id;
145
  }
146
  }
147
-
148
  $bundle_data = maybe_unserialize(get_post_meta($product_id,'_bundle_data', true));
149
-
150
  if(empty($bundle_data) || $bundle_data==false){
151
  $isbundle = false;
152
  }
153
-
154
  if(!$isbundle){
155
  return;
156
  }
157
-
158
  if($default_language == $lang){
159
  $template_data['original'] = true;
160
  }else{
161
  $template_data['original'] = false;
162
  }
163
-
164
  if (!$translated ) {
165
  $template_data['empty_translation'] = true;
166
  $template_data['product_bundles'] = array();
@@ -171,10 +136,8 @@ class WCML_Product_Bundles{
171
  $tr_bundles_ids[$k] = apply_filters( 'translate_object_id',$original_id,'product',false,$lang);
172
  $k++;
173
  }
174
-
175
  $template_data['product_bundles'] = $tr_bundles_ids;
176
- $tr_bundles_ids = $template_data['product_bundles'];
177
-
178
  if (empty($tr_bundles_ids)) {
179
  $template_data['empty_bundles'] = true;
180
  $template_data['product_bundles'] = array();
@@ -182,132 +145,80 @@ class WCML_Product_Bundles{
182
  if ($default_language == $lang) {
183
  $template_data['product_bundles'] = $tr_bundles_ids;
184
  }
185
-
186
  foreach ($product_bundles as $bundle_id) {
187
  $bundles_texts = array();
188
  $bundle_name = get_the_title($bundle_id);
189
-
190
  if(isset($bundle_data[$bundle_id]['override_title']) && $bundle_data[$bundle_id]['override_title']=='yes'){
191
  $bundle_title = $bundle_data[$bundle_id]['product_title'];
192
  $template_data['bundles_data'][$bundle_name]['override_bundle_title'] = 'yes';
193
  }else{
194
  $bundle_title = get_the_title($bundle_id);
195
  }
196
-
197
  if(isset($bundle_data[$bundle_id]['override_description']) && $bundle_data[$bundle_id]['override_description']=='yes'){
198
  $bundle_desc = $bundle_data[$bundle_id]['product_description'];
199
  $template_data['bundles_data'][$bundle_name]['override_bundle_desc'] = 'yes';
200
  }else{
201
  $bundle_prod = get_post($bundle_id);
202
- $bundle_desc = $bundle_prod->post_excerpt;
203
  }
204
-
205
  $template_data['bundles_data'][$bundle_name]['bundle_title'] = $bundle_title;
206
  $template_data['bundles_data'][$bundle_name]['bundle_desc'] = $bundle_desc;
207
  }
208
-
209
  }
210
  }
211
  include WCML_PLUGIN_PATH . '/compatibility/templates/bundles_box.php';
212
  }
213
-
214
- // Update bundled_by cart keys and stamp when language is switched
215
- function cart_contents_bundle_update_lang_switch($cart_contents,$key,$new_key,$current_language){
216
- $exist_ids_translations = array();
217
-
218
- if(isset($cart_contents[$key]['bundled_items'])){
219
- foreach($cart_contents[$key]['bundled_items'] as $index=>$bundled_key){
220
- if($cart_contents[$bundled_key]['bundled_by'] == $key){
221
- $cart_contents[$bundled_key]['bundled_by'] = $new_key;
222
- }
223
- }
224
- }
225
-
226
- if(isset($cart_contents[$key]['stamp'])){
227
- global $woocommerce_wpml;
228
- $new_stamp = array();
229
- foreach( $cart_contents[$key]['stamp'] as $st_prd => $st_prod_data){
230
- $tr_st_p_id = apply_filters( 'translate_object_id',$st_prd,'product',false,$current_language);
231
-
232
- if(isset($st_prod_data['variation_id'])){
233
- if(array_key_exists($st_prod_data['variation_id'],$exist_ids_translations)){
234
- $tr_st_v_id = $exist_ids_translations[$st_prod_data['variation_id']];
235
- }else{
236
- $tr_st_v_id = apply_filters( 'translate_object_id',$st_prod_data['variation_id'],'product_variation',false,$current_language);
237
- }
238
-
239
- if(!is_null($tr_st_v_id)){
240
- $st_prod_data['variation_id'] = $tr_st_v_id;
241
- $exist_ids_translations[$st_prod_data['variation_id']] = $tr_st_v_id;
242
- }
243
-
244
- foreach($st_prod_data['attributes'] as $taxonomy=>$attribute){
245
- if (substr($taxonomy, 0, 10) == 'attribute_') {
246
- $tax = substr($taxonomy, 10);
247
- }else{
248
- $tax = $taxonomy;
249
- }
250
- $st_prod_data['attributes'][$taxonomy] = $woocommerce_wpml->products->get_cart_attribute_translation($tax,$attribute,$st_prod_data['product_id'],$tr_st_p_id,$current_language);
251
- }
252
-
253
- }
254
-
255
- if(!is_null($tr_st_p_id)){
256
- $st_prod_data['product_id'] = $tr_st_p_id;
257
- $new_stamp[$tr_st_p_id] = $st_prod_data;
258
- $exist_ids_translations[$st_prd] = $tr_st_p_id;
259
- }
260
- }
261
-
262
- $cart_contents[$key]['stamp'] = $new_stamp;
263
- }
264
- return $cart_contents;
265
- }
266
-
267
- // Update bundled items cart keys when language is switched
268
- function cart_bundle_update_lang_switch($new_cart_data,$cart_contents, $key, $new_key){
269
-
270
- if(isset($cart_contents[$key]['bundled_by']) && isset($new_cart_data[$cart_contents[$key]['bundled_by']])){
271
- global $woocommerce;
272
- $buff = $new_cart_data[$new_key];
273
- $key_item = $woocommerce->cart->generate_cart_id( $new_cart_data[$new_key]['product_id'], $new_cart_data[$new_key]['variation_id'], $new_cart_data[$new_key]['variation'], array( 'bundled_item_id' => $new_cart_data[$new_key]['product_id'], 'bundled_by' => $new_cart_data[$new_key]['bundled_by'], 'stamp' => $new_cart_data[$new_key][ 'stamp' ], 'dynamic_pricing_allowed' => 'no' ) );
274
-
275
- foreach($new_cart_data[$cart_contents[$key]['bundled_by']]['bundled_items'] as $index => $item){
276
- if($item == $key){
277
- $new_cart_data[$cart_contents[$key]['bundled_by']]['bundled_items'][$index] = $key_item;
278
- }
279
- }
280
-
281
- unset($new_cart_data[$new_key]);
282
- $new_cart_data[$key_item] = $buff;
283
- }
284
- return $new_cart_data;
285
- }
286
-
287
- function filter_cart_item_data ( $cart_contents ){
288
- unset( $cart_contents['bundled_items'] );
289
-
290
- return $cart_contents;
291
  }
292
-
293
- function removeduplicated_bundle_product_in_cart( $cart_contents, $key, $cart_item ){
294
- if( isset( $cart_item['bundled_by'] ) && !isset($cart_contents[$cart_item['bundled_by']])){
295
- unset($cart_contents[$key]);
296
- }
297
-
298
- return $cart_contents;
 
299
  }
300
-
301
- function check_on_bundle_product_in_cart( $flag, $cart_item ){
302
-
303
- if( isset( $cart_item['bundled_by'] ) ) {
304
- return true;
305
- }
306
-
307
- return false;
308
-
309
- }
310
-
311
-
312
  }
313
-
1
  <?php
 
2
  class WCML_Product_Bundles{
 
3
  function __construct(){
4
+ add_action('wcml_gui_additional_box',array($this,'product_bundles_box'),10,3);
5
+ add_action('wcml_after_duplicate_product_post_meta',array($this,'sync_bundled_ids'),10,3);
6
+ add_action('wcml_extra_titles',array($this,'product_bundles_title'),10,1);
7
+ add_action('wcml_update_extra_fields',array($this,'bundle_update'),10,2);
8
+ add_action('woocommerce_get_cart_item_from_session', array( $this, 'resync_bundle'),5,3);
9
+ add_filter('woocommerce_cart_loaded_from_session', array($this, 'resync_bundle_clean'),10);
10
+ add_filter('wcml_exception_duplicate_products_in_cart', array($this, 'bundles_duplicate_exception'),10,2);
 
 
11
  }
 
12
  // Sync Bundled product '_bundle_data' with translated values when the product is duplicated
13
  function sync_bundled_ids($original_product_id, $trnsl_product_id, $data = false){
14
  global $sitepress;
 
15
  $atts = maybe_unserialize(get_post_meta($original_product_id, '_bundle_data', true));
 
16
  if( $atts ){
17
  $lang = $sitepress->get_language_for_element($trnsl_product_id,'post_product');
18
  $tr_ids = array();
19
  $i = 2;
20
  foreach($atts as $id=>$bundle_data){
21
  $tr_id = apply_filters( 'translate_object_id',$id,get_post_type($id),true,$lang);
 
22
  if(isset($tr_bundle[$tr_id])){
23
  $bundle_key = $tr_id.'_'.$i;
24
  $i++;
25
  }else{
26
  $bundle_key = $tr_id;
27
  }
 
28
  $tr_bundle[$bundle_key] = $bundle_data;
 
29
  $tr_bundle[$bundle_key]['product_id'] = $tr_id;
 
30
  if(isset($bundle_data['product_title'])){
31
  if($bundle_data['override_title']=='yes'){
32
  $tr_bundle[$bundle_key]['product_title'] = '';
35
  $tr_bundle[$bundle_key]['product_title'] = $tr_title;
36
  }
37
  }
 
38
  if(isset($bundle_data['product_description'])){
39
  if($bundle_data['override_description']=='yes'){
40
  $tr_bundle[$bundle_key]['product_description'] = '';
44
  $tr_bundle[$bundle_key]['product_description'] = $tr_desc;
45
  }
46
  }
 
47
  if(isset($bundle_data['filter_variations']) && $bundle_data['filter_variations']=='yes'){
48
  $allowed_var = $bundle_data['allowed_variations'];
49
  foreach($allowed_var as $key=>$var_id){
51
  $tr_bundle[$bundle_key]['allowed_variations'][$key] = $tr_var_id;
52
  }
53
  }
 
54
  if(isset($bundle_data['bundle_defaults']) && !empty($bundle_data['bundle_defaults'])){
55
  foreach($bundle_data['bundle_defaults'] as $tax=>$term_slug){
 
56
  global $woocommerce_wpml;
57
  $term_id = $woocommerce_wpml->products->wcml_get_term_id_by_slug( $tax, $term_slug );
 
58
  if( $term_id ){
59
  // Global Attribute
60
  $tr_def_id = apply_filters( 'translate_object_id',$term_id,$tax,true,$lang);
70
  $tr_bundle[$bundle_key]['bundle_defaults'][$tax] = $tr_meta;
71
  endwhile;
72
  }
 
73
  }
74
  }
 
 
75
  }
 
76
  update_post_meta($trnsl_product_id,'_bundle_data',$tr_bundle);
77
  }
 
78
  }
 
79
  // Update Bundled products title and descritpion after saving the translation
80
  function bundle_update($tr_id, $data){
 
81
  global $sitepress;
82
  $tr_bundle_data = array();
83
+ $tr_bundle_data = maybe_unserialize(get_post_meta($tr_id,'_bundle_data', true));
 
84
  if(!empty($data['bundles'])){
85
  foreach($data['bundles'] as $bundle_id => $bundle_data){
86
  if(isset($tr_bundle_data[$bundle_id])){
88
  $tr_bundle_data[$bundle_id]['product_description'] = $bundle_data['bundle_desc'];
89
  }
90
  }
91
+ update_post_meta( $tr_id, '_bundle_data', $tr_bundle_data );
92
  $tr_bundle_data = array();
93
  }
 
94
  }
 
95
  // Add 'Product Bundles' title to the WCML Product GUI if the current product is a bundled product
96
  function product_bundles_title($product_id){
97
  $bundle_data = maybe_unserialize(get_post_meta($product_id,'_bundle_data', true));
99
  <th scope="col"><?php _e('Product Bundles', 'wcml_product_bundles'); ?></th>
100
  <?php }
101
  }
 
102
  // Add Bundles Box to WCML Translation GUI
103
  function product_bundles_box($product_id,$lang, $is_duplicate_product = false ) {
104
  global $sitepress, $woocommerce_wpml;
105
  $isbundle = true;
106
  $translated = true;
107
  $template_data = array();
 
108
  $default_language = $woocommerce_wpml->products->get_original_product_language( $product_id );
 
 
109
  if($default_language != $lang){
110
  $tr_product_id = apply_filters( 'translate_object_id',$product_id, 'product', true, $lang);
111
  if($tr_product_id == $product_id){
114
  $product_id = $tr_product_id;
115
  }
116
  }
 
117
  $bundle_data = maybe_unserialize(get_post_meta($product_id,'_bundle_data', true));
 
118
  if(empty($bundle_data) || $bundle_data==false){
119
  $isbundle = false;
120
  }
 
121
  if(!$isbundle){
122
  return;
123
  }
 
124
  if($default_language == $lang){
125
  $template_data['original'] = true;
126
  }else{
127
  $template_data['original'] = false;
128
  }
 
129
  if (!$translated ) {
130
  $template_data['empty_translation'] = true;
131
  $template_data['product_bundles'] = array();
136
  $tr_bundles_ids[$k] = apply_filters( 'translate_object_id',$original_id,'product',false,$lang);
137
  $k++;
138
  }
 
139
  $template_data['product_bundles'] = $tr_bundles_ids;
140
+ $tr_bundles_ids = $template_data['product_bundles'];
 
141
  if (empty($tr_bundles_ids)) {
142
  $template_data['empty_bundles'] = true;
143
  $template_data['product_bundles'] = array();
145
  if ($default_language == $lang) {
146
  $template_data['product_bundles'] = $tr_bundles_ids;
147
  }
 
148
  foreach ($product_bundles as $bundle_id) {
149
  $bundles_texts = array();
150
  $bundle_name = get_the_title($bundle_id);
 
151
  if(isset($bundle_data[$bundle_id]['override_title']) && $bundle_data[$bundle_id]['override_title']=='yes'){
152
  $bundle_title = $bundle_data[$bundle_id]['product_title'];
153
  $template_data['bundles_data'][$bundle_name]['override_bundle_title'] = 'yes';
154
  }else{
155
  $bundle_title = get_the_title($bundle_id);
156
  }
 
157
  if(isset($bundle_data[$bundle_id]['override_description']) && $bundle_data[$bundle_id]['override_description']=='yes'){
158
  $bundle_desc = $bundle_data[$bundle_id]['product_description'];
159
  $template_data['bundles_data'][$bundle_name]['override_bundle_desc'] = 'yes';
160
  }else{
161
  $bundle_prod = get_post($bundle_id);
162
+ $bundle_desc = $bundle_prod->post_excerpt;
163
  }
 
164
  $template_data['bundles_data'][$bundle_name]['bundle_title'] = $bundle_title;
165
  $template_data['bundles_data'][$bundle_name]['bundle_desc'] = $bundle_desc;
166
  }
 
167
  }
168
  }
169
  include WCML_PLUGIN_PATH . '/compatibility/templates/bundles_box.php';
170
  }
171
+ function resync_bundle( $cart_item, $session_values, $cart_item_key ) {
172
+ if ( isset( $cart_item[ 'bundled_items' ] ) && $cart_item[ 'data' ]->product_type === 'bundle' ) {
173
+ $current_bundle_id = apply_filters( 'translate_object_id', $cart_item[ 'product_id' ], 'product', true );
174
+ if ( $cart_item[ 'product_id' ] != $current_bundle_id ) {
175
+ $old_bundled_item_ids = array_keys( $cart_item[ 'data' ]->bundle_data );
176
+ $cart_item[ 'data' ] = wc_get_product( $current_bundle_id );
177
+ $new_bundled_item_ids = array_keys( $cart_item[ 'data' ]->bundle_data );
178
+ $remapped_bundled_item_ids = array();
179
+ foreach ( $old_bundled_item_ids as $old_item_id_index => $old_item_id ) {
180
+ $remapped_bundled_item_ids[ $old_item_id ] = $new_bundled_item_ids[ $old_item_id_index ];
181
+ }
182
+ $cart_item[ 'remapped_bundled_item_ids' ] = $remapped_bundled_item_ids;
183
+ if ( isset( $cart_item[ 'stamp' ] ) ) {
184
+ $new_stamp = array();
185
+ foreach ( $cart_item[ 'stamp' ] as $bundled_item_id => $stamp_data ) {
186
+ $new_stamp[ $remapped_bundled_item_ids[ $bundled_item_id ] ] = $stamp_data;
187
+ }
188
+ $cart_item[ 'stamp' ] = $new_stamp;
189
+ }
190
+ }
191
+ }
192
+ if ( isset( $cart_item[ 'bundled_by' ] ) && isset( WC()->cart->cart_contents[ $cart_item[ 'bundled_by' ] ] ) ) {
193
+ $bundle_cart_item = WC()->cart->cart_contents[ $cart_item[ 'bundled_by' ] ];
194
+ if ( isset( $bundle_cart_item[ 'remapped_bundled_item_ids' ] ) && isset( $cart_item[ 'bundled_item_id' ] ) && isset( $bundle_cart_item[ 'remapped_bundled_item_ids' ][ $cart_item[ 'bundled_item_id' ] ] ) ) {
195
+ $old_id = $cart_item[ 'bundled_item_id' ];
196
+ $remapped_bundled_item_ids = $bundle_cart_item[ 'remapped_bundled_item_ids' ];
197
+ $cart_item[ 'bundled_item_id' ] = $remapped_bundled_item_ids[ $cart_item[ 'bundled_item_id' ] ];
198
+ if ( isset( $cart_item[ 'stamp' ] ) ) {
199
+ $new_stamp = array();
200
+ foreach ( $cart_item[ 'stamp' ] as $bundled_item_id => $stamp_data ) {
201
+ $new_stamp[ $remapped_bundled_item_ids[ $bundled_item_id ] ] = $stamp_data;
202
+ }
203
+ $cart_item[ 'stamp' ] = $new_stamp;
204
+ }
205
+ }
206
+ }
207
+ return $cart_item;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
208
  }
209
+ function resync_bundle_clean( $cart ) {
210
+ foreach ( $cart->cart_contents as $cart_item_key => $cart_item ) {
211
+ if ( isset( $cart_item[ 'bundled_items' ] ) && $cart_item[ 'data' ]->product_type === 'bundle' ) {
212
+ if ( isset( $cart_item[ 'remapped_bundled_item_ids' ] ) ) {
213
+ unset( WC()->cart->cart_contents[ $cart_item_key ][ 'remapped_bundled_item_ids' ] );
214
+ }
215
+ }
216
+ }
217
  }
218
+ function bundles_duplicate_exception( $exclude, $cart_item ) {
219
+ if ( isset( $cart_item[ 'bundled_items' ] ) || isset( $cart_item[ 'bundled_by' ] ) ) {
220
+ $exclude = true;
221
+ }
222
+ return $exclude;
223
+ }
 
 
 
 
 
 
224
  }
 
inc/emails.class.php CHANGED
@@ -1,14 +1,16 @@
1
  <?php
2
- class WCML_Emails{
3
 
4
  private $order_id = false;
5
 
6
  private $locale = false;
7
 
8
- function __construct(){
9
-
10
- add_action('init', array($this, 'init'));
11
-
 
 
12
  }
13
 
14
  function init(){
@@ -108,14 +110,9 @@ class WCML_Emails{
108
 
109
  /**
110
  * After email translation switch language to default.
111
- *
112
- * @global type $sitepress
113
- * @return type
114
  */
115
  function email_footer() {
116
- global $sitepress;
117
- $sitepress->switch_lang($sitepress->get_default_language());
118
-
119
  }
120
 
121
  function comments_language(){
@@ -234,7 +231,7 @@ class WCML_Emails{
234
 
235
 
236
  function icl_job_edit_url($link,$job_id){
237
- global $wpdb,$sitepress,$iclTranslationManagement;
238
 
239
  $trid = $wpdb->get_var($wpdb->prepare("
240
  SELECT t.trid
1
  <?php
2
+ class WCML_Emails extends WPML_SP_User {
3
 
4
  private $order_id = false;
5
 
6
  private $locale = false;
7
 
8
+ /**
9
+ * @param SitePress $sitepress
10
+ */
11
+ function __construct( &$sitepress ) {
12
+ parent::__construct( $sitepress );
13
+ add_action( 'init', array( $this, 'init' ) );
14
  }
15
 
16
  function init(){
110
 
111
  /**
112
  * After email translation switch language to default.
 
 
 
113
  */
114
  function email_footer() {
115
+ $this->sitepress->switch_lang( $this->sitepress->get_default_language() );
 
 
116
  }
117
 
118
  function comments_language(){
231
 
232
 
233
  function icl_job_edit_url($link,$job_id){
234
+ global $wpdb, $iclTranslationManagement;
235
 
236
  $trid = $wpdb->get_var($wpdb->prepare("
237
  SELECT t.trid
inc/endpoints.class.php CHANGED
@@ -185,7 +185,7 @@ class WCML_Endpoints{
185
  $current_id = $q->queried_object_id;
186
  }
187
 
188
- if( !$q->is_404 && $current_id == $my_account_id ){
189
 
190
  $uri_vars = array_filter( explode( '/', $_SERVER['REQUEST_URI']) );
191
  $endpoints = WC()->query->get_query_vars();
185
  $current_id = $q->queried_object_id;
186
  }
187
 
188
+ if( !$q->is_404 && $current_id == $my_account_id && $q->is_page ){
189
 
190
  $uri_vars = array_filter( explode( '/', $_SERVER['REQUEST_URI']) );
191
  $endpoints = WC()->query->get_query_vars();
inc/multi-currency.class.php CHANGED
@@ -95,6 +95,8 @@ class WCML_WC_MultiCurrency{
95
  //filter query to get order by status
96
  add_filter( 'query', array( $this, 'filter_order_status_query' ) );
97
  }
 
 
98
  }
99
 
100
 
@@ -819,6 +821,8 @@ class WCML_WC_MultiCurrency{
819
  function woocommerce_product_options_custom_pricing(){
820
  global $pagenow,$sitepress,$woocommerce_wpml;
821
 
 
 
822
  if( ( isset($_GET['post'] ) && ( get_post_type($_GET['post']) != 'product' || !$woocommerce_wpml->products->is_original_product( $_GET['post'] ) ) ) ||
823
  ( isset($_GET['post_type'] ) && $_GET['post_type'] == 'product' && isset( $_GET['source_lang'] ) ) ){
824
  return;
@@ -834,7 +838,6 @@ class WCML_WC_MultiCurrency{
834
 
835
  wp_nonce_field('wcml_save_custom_prices','_wcml_custom_prices_nonce');
836
 
837
- $this->load_custom_prices_js_css();
838
  }
839
 
840
  function custom_pricing_output($post_id = false){
@@ -853,6 +856,12 @@ class WCML_WC_MultiCurrency{
853
  include WCML_PLUGIN_PATH . '/menu/sub/custom-prices.php';
854
  }
855
 
 
 
 
 
 
 
856
  function load_custom_prices_js_css(){
857
  wp_register_style('wpml-wcml-prices', WCML_PLUGIN_URL . '/assets/css/wcml-prices.css', null, WCML_VERSION);
858
  wp_register_script('wcml-tm-scripts-prices', WCML_PLUGIN_URL . '/assets/js/prices.js', array('jquery'), WCML_VERSION);
95
  //filter query to get order by status
96
  add_filter( 'query', array( $this, 'filter_order_status_query' ) );
97
  }
98
+
99
+ add_action( 'woocommerce_variation_options', array( $this, 'add_individual_variation_nonce' ), 10, 3 );
100
  }
101
 
102
 
821
  function woocommerce_product_options_custom_pricing(){
822
  global $pagenow,$sitepress,$woocommerce_wpml;
823
 
824
+ $this->load_custom_prices_js_css();
825
+
826
  if( ( isset($_GET['post'] ) && ( get_post_type($_GET['post']) != 'product' || !$woocommerce_wpml->products->is_original_product( $_GET['post'] ) ) ) ||
827
  ( isset($_GET['post_type'] ) && $_GET['post_type'] == 'product' && isset( $_GET['source_lang'] ) ) ){
828
  return;
838
 
839
  wp_nonce_field('wcml_save_custom_prices','_wcml_custom_prices_nonce');
840
 
 
841
  }
842
 
843
  function custom_pricing_output($post_id = false){
856
  include WCML_PLUGIN_PATH . '/menu/sub/custom-prices.php';
857
  }
858
 
859
+ function add_individual_variation_nonce($loop, $variation_data, $variation){
860
+
861
+ wp_nonce_field('wcml_save_custom_prices_variation_' . $variation->ID, '_wcml_custom_prices_variation_' . $variation->ID . '_nonce');
862
+
863
+ }
864
+
865
  function load_custom_prices_js_css(){
866
  wp_register_style('wpml-wcml-prices', WCML_PLUGIN_URL . '/assets/css/wcml-prices.css', null, WCML_VERSION);
867
  wp_register_script('wcml-tm-scripts-prices', WCML_PLUGIN_URL . '/assets/js/prices.js', array('jquery'), WCML_VERSION);
inc/products.class.php CHANGED
@@ -32,6 +32,8 @@ class WCML_Products{
32
  add_action( 'save_post', array( $this, 'sync_post_action' ), 11, 2 ); // After WPML
33
  //when save new attachment duplicate product gallery
34
  add_action( 'wpml_media_create_duplicate_attachment', array( $this, 'sync_product_gallery_duplicate_attachment' ), 11, 2 );
 
 
35
 
36
  add_filter( 'icl_make_duplicate', array( $this, 'icl_make_duplicate'), 11, 4 );
37
 
@@ -110,7 +112,7 @@ class WCML_Products{
110
  add_filter( 'woocommerce_cached_widget_id', array( $this, 'override_cached_widget_id' ) );
111
 
112
  //update menu_order fro translations after ordering original products
113
- add_action( 'woocommerce_after_product_ordering', array( $this, 'update_translations_product_ordering' ) );
114
 
115
  //filter to copy excerpt value
116
  add_filter( 'wpml_copy_from_original_custom_fields', array( $this, 'filter_excerpt_field_content_copy' ) );
@@ -1575,34 +1577,7 @@ class WCML_Products{
1575
  }
1576
 
1577
  //save custom prices
1578
- $nonce = filter_input( INPUT_POST, '_wcml_custom_prices_nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
1579
-
1580
- if( isset( $_POST[ '_wcml_custom_prices' ] ) && isset( $nonce ) && wp_verify_nonce( $nonce, 'wcml_save_custom_prices' )){
1581
-
1582
- if( isset( $_POST[ '_wcml_custom_prices' ][ $post_id ] ) ) {
1583
- $wcml_custom_prices_option = $_POST[ '_wcml_custom_prices' ][ $post_id ];
1584
- }else{
1585
- $wcml_custom_prices_option = $_POST[ '_wcml_custom_prices' ][ 0 ];
1586
- }
1587
-
1588
- update_post_meta( $post_id, '_wcml_custom_prices_status', $wcml_custom_prices_option );
1589
-
1590
- if( $wcml_custom_prices_option == 1){
1591
-
1592
- $currencies = $woocommerce_wpml->multi_currency_support->get_currencies();
1593
-
1594
- foreach( $currencies as $code => $currency ){
1595
- $sale_price = $_POST[ '_custom_sale_price' ][ $code ];
1596
- $regular_price = $_POST[ '_custom_regular_price' ][ $code ];
1597
-
1598
- $date_from = strtotime( $_POST[ '_custom_sale_price_dates_from' ][ $code ] );
1599
- $date_to = strtotime( $_POST[ '_custom_sale_price_dates_to' ][ $code ] );
1600
- $schedule = $_POST[ '_wcml_schedule' ][ $code ];
1601
-
1602
- $pr_price = $this->update_custom_prices( $post_id, $regular_price, $sale_price, $schedule, $date_from, $date_to, $code );
1603
- }
1604
- }
1605
- }
1606
 
1607
  // pick posts to sync
1608
  $posts = array();
@@ -1635,6 +1610,8 @@ class WCML_Products{
1635
  $this->sync_default_product_attr( $duplicated_post_id, $post_id, $lang );
1636
 
1637
  $this->sync_product_attr( $duplicated_post_id, $post_id );
 
 
1638
 
1639
  // synchronize post variations
1640
  $this->sync_product_variations( $duplicated_post_id, $post_id, $lang );
@@ -1644,6 +1621,88 @@ class WCML_Products{
1644
  $this->sync_product_variations_custom_prices( $duplicated_post_id );
1645
  }
1646
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1647
  //sync product parent & post_status
1648
  function sync_status_and_parent( $duplicated_post_id, $post_id, $lang ){
1649
  global $wpdb,$woocommerce_wpml;
@@ -1714,7 +1773,7 @@ class WCML_Products{
1714
  return $price;
1715
  }
1716
 
1717
- function sync_product_variations_custom_prices($product_id){
1718
  global $wpdb,$woocommerce_wpml;
1719
  $is_variable_product = $this->is_variable_product($product_id);
1720
 
@@ -1727,10 +1786,14 @@ class WCML_Products{
1727
  foreach($get_all_post_variations as $k => $post_data){
1728
  $duplicated_post_variation_ids[] = $post_data->ID;
1729
 
1730
- //save custom prices for variation
1731
- $nonce = filter_input( INPUT_POST, '_wcml_custom_prices_nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
1732
 
1733
- if(isset( $_POST['_wcml_custom_prices'][$post_data->ID]) && isset( $nonce ) && wp_verify_nonce( $nonce, 'wcml_save_custom_prices' )){
 
 
 
 
 
 
1734
 
1735
  update_post_meta($post_data->ID,'_wcml_custom_prices_status',$_POST['_wcml_custom_prices'][$post_data->ID]);
1736
 
@@ -2905,7 +2968,7 @@ class WCML_Products{
2905
 
2906
 
2907
  //update menu_order fro translations after ordering original products
2908
- function update_translations_product_ordering(){
2909
  global $wpdb, $sitepress, $woocommerce_wpml;
2910
 
2911
  if( $woocommerce_wpml->settings['products_sync_order'] ) {
@@ -2913,21 +2976,37 @@ class WCML_Products{
2913
  $current_language = $sitepress->get_current_language();
2914
 
2915
  if ($current_language == $sitepress->get_default_language()) {
2916
- $products = $wpdb->get_results($wpdb->prepare("SELECT p.ID, p.menu_order FROM $wpdb->posts AS p LEFT JOIN {$wpdb->prefix}icl_translations AS icl ON icl.element_id = p.id WHERE p.post_type = 'product' AND p.post_status IN ( 'publish', 'future', 'draft', 'pending', 'private' ) AND icl.element_type= 'post_product' AND icl.language_code = %s", $current_language));
2917
 
2918
  foreach ($products as $product) {
 
 
 
 
 
 
 
 
 
 
 
 
 
2919
 
2920
- $trid = $sitepress->get_element_trid($product->ID, 'post_product');
 
 
 
2921
  $translations = $sitepress->get_element_translations($trid, 'post_product');
2922
 
2923
  foreach ($translations as $translation) {
2924
 
2925
- if ($translation->element_id != $product->ID) {
2926
- $wpdb->update($wpdb->posts, array('menu_order' => $product->menu_order), array('ID' => $translation->element_id));
2927
- }
2928
  }
2929
  }
2930
  }
 
2931
  }
2932
  }
2933
 
32
  add_action( 'save_post', array( $this, 'sync_post_action' ), 11, 2 ); // After WPML
33
  //when save new attachment duplicate product gallery
34
  add_action( 'wpml_media_create_duplicate_attachment', array( $this, 'sync_product_gallery_duplicate_attachment' ), 11, 2 );
35
+ add_action( 'woocommerce_ajax_save_product_variations', array( $this, 'sync_product_variations_action' ), 11 );
36
+ add_action( 'wp_ajax_woocommerce_remove_variations', array( $this, 'remove_translations_for_variations' ), 9 );
37
 
38
  add_filter( 'icl_make_duplicate', array( $this, 'icl_make_duplicate'), 11, 4 );
39
 
112
  add_filter( 'woocommerce_cached_widget_id', array( $this, 'override_cached_widget_id' ) );
113
 
114
  //update menu_order fro translations after ordering original products
115
+ add_action( 'woocommerce_after_product_ordering', array( $this, 'update_all_products_translations_ordering' ) );
116
 
117
  //filter to copy excerpt value
118
  add_filter( 'wpml_copy_from_original_custom_fields', array( $this, 'filter_excerpt_field_content_copy' ) );
1577
  }
1578
 
1579
  //save custom prices
1580
+ $this->save_custom_prices($post_id);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1581
 
1582
  // pick posts to sync
1583
  $posts = array();
1610
  $this->sync_default_product_attr( $duplicated_post_id, $post_id, $lang );
1611
 
1612
  $this->sync_product_attr( $duplicated_post_id, $post_id );
1613
+
1614
+ $this->update_order_for_product_translations( $duplicated_post_id );
1615
 
1616
  // synchronize post variations
1617
  $this->sync_product_variations( $duplicated_post_id, $post_id, $lang );
1621
  $this->sync_product_variations_custom_prices( $duplicated_post_id );
1622
  }
1623
 
1624
+
1625
+ function sync_product_variations_action( $product_id ){
1626
+ global $sitepress, $wpdb;
1627
+
1628
+ if( $this->is_original_product( $product_id ) ){
1629
+
1630
+ $this->sync_product_variations_custom_prices( $product_id );
1631
+
1632
+ $trid = $sitepress->get_element_trid( $product_id, 'post_product' );
1633
+ if ( empty( $trid ) ) {
1634
+ $trid = $wpdb->get_var( $wpdb->prepare( "SELECT trid FROM {$wpdb->prefix}icl_translations WHERE element_id = %d AND element_type = 'post_product'", $product_id ) );
1635
+ }
1636
+
1637
+ $translations = $sitepress->get_element_translations( $trid, 'post_product' );
1638
+ foreach ( $translations as $translation ) {
1639
+ if ( !$translation->original ) {
1640
+ $this->sync_product_variations($product_id, $translation->element_id, $translation->language_code);
1641
+ }
1642
+ }
1643
+
1644
+ }
1645
+ }
1646
+
1647
+ function remove_translations_for_variations(){
1648
+ check_ajax_referer( 'delete-variations', 'security' );
1649
+
1650
+ if ( ! current_user_can( 'edit_products' ) ) {
1651
+ die(-1);
1652
+ }
1653
+
1654
+ global $sitepress;
1655
+
1656
+ $variation_ids = (array) $_POST['variation_ids'];
1657
+
1658
+ foreach ( $variation_ids as $variation_id ) {
1659
+
1660
+ $trid = $sitepress->get_element_trid( $variation_id, 'post_product_variation' );
1661
+ $translations = $sitepress->get_element_translations( $trid, 'post_product_variation' );
1662
+
1663
+ foreach ( $translations as $translation ) {
1664
+ if ( !$translation->original ) {
1665
+ wp_delete_post( $translation->element_id );
1666
+ }
1667
+ }
1668
+
1669
+ }
1670
+
1671
+ }
1672
+
1673
+ function save_custom_prices($post_id){
1674
+ global $woocommerce_wpml;
1675
+
1676
+ $nonce = filter_input( INPUT_POST, '_wcml_custom_prices_nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
1677
+
1678
+ if( isset( $_POST[ '_wcml_custom_prices' ] ) && isset( $nonce ) && wp_verify_nonce( $nonce, 'wcml_save_custom_prices' )){
1679
+
1680
+ if( isset( $_POST[ '_wcml_custom_prices' ][ $post_id ] ) ) {
1681
+ $wcml_custom_prices_option = $_POST[ '_wcml_custom_prices' ][ $post_id ];
1682
+ }else{
1683
+ $wcml_custom_prices_option = $_POST[ '_wcml_custom_prices' ][ 0 ];
1684
+ }
1685
+
1686
+ update_post_meta( $post_id, '_wcml_custom_prices_status', $wcml_custom_prices_option );
1687
+
1688
+ if( $wcml_custom_prices_option == 1){
1689
+
1690
+ $currencies = $woocommerce_wpml->multi_currency_support->get_currencies();
1691
+
1692
+ foreach( $currencies as $code => $currency ){
1693
+ $sale_price = $_POST[ '_custom_sale_price' ][ $code ];
1694
+ $regular_price = $_POST[ '_custom_regular_price' ][ $code ];
1695
+
1696
+ $date_from = strtotime( $_POST[ '_custom_sale_price_dates_from' ][ $code ] );
1697
+ $date_to = strtotime( $_POST[ '_custom_sale_price_dates_to' ][ $code ] );
1698
+ $schedule = $_POST[ '_wcml_schedule' ][ $code ];
1699
+
1700
+ $this->update_custom_prices( $post_id, $regular_price, $sale_price, $schedule, $date_from, $date_to, $code );
1701
+ }
1702
+ }
1703
+ }
1704
+ }
1705
+
1706
  //sync product parent & post_status
1707
  function sync_status_and_parent( $duplicated_post_id, $post_id, $lang ){
1708
  global $wpdb,$woocommerce_wpml;
1773
  return $price;
1774
  }
1775
 
1776
+ function sync_product_variations_custom_prices( $product_id ){
1777
  global $wpdb,$woocommerce_wpml;
1778
  $is_variable_product = $this->is_variable_product($product_id);
1779
 
1786
  foreach($get_all_post_variations as $k => $post_data){
1787
  $duplicated_post_variation_ids[] = $post_data->ID;
1788
 
 
 
1789
 
1790
+ if( !isset( $_POST['_wcml_custom_prices'][$post_data->ID] ) ){
1791
+ continue; // save changes for individual variation
1792
+ }
1793
+
1794
+ //save custom prices for variation
1795
+ $nonce = filter_input( INPUT_POST, '_wcml_custom_prices_variation_' . $post_data->ID . '_nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
1796
+ if(isset( $_POST['_wcml_custom_prices'][$post_data->ID]) && isset( $nonce ) && wp_verify_nonce( $nonce, 'wcml_save_custom_prices_variation_' . $post_data->ID )){
1797
 
1798
  update_post_meta($post_data->ID,'_wcml_custom_prices_status',$_POST['_wcml_custom_prices'][$post_data->ID]);
1799
 
2968
 
2969
 
2970
  //update menu_order fro translations after ordering original products
2971
+ function update_all_products_translations_ordering(){
2972
  global $wpdb, $sitepress, $woocommerce_wpml;
2973
 
2974
  if( $woocommerce_wpml->settings['products_sync_order'] ) {
2976
  $current_language = $sitepress->get_current_language();
2977
 
2978
  if ($current_language == $sitepress->get_default_language()) {
2979
+ $products = $wpdb->get_results($wpdb->prepare("SELECT p.ID FROM $wpdb->posts AS p LEFT JOIN {$wpdb->prefix}icl_translations AS icl ON icl.element_id = p.id WHERE p.post_type = 'product' AND p.post_status IN ( 'publish', 'future', 'draft', 'pending', 'private' ) AND icl.element_type= 'post_product' AND icl.language_code = %s", $current_language));
2980
 
2981
  foreach ($products as $product) {
2982
+ $this->update_order_for_product_translations( $product->ID );
2983
+ }
2984
+ }
2985
+ }
2986
+ }
2987
+
2988
+ //update menu_order fro translations after ordering original products
2989
+ function update_order_for_product_translations( $product_id ){
2990
+ global $wpdb, $sitepress, $woocommerce_wpml;
2991
+
2992
+ if( $woocommerce_wpml->settings['products_sync_order'] ) {
2993
+
2994
+ $current_language = $sitepress->get_current_language();
2995
 
2996
+ if ( $current_language == $sitepress->get_default_language() ) {
2997
+ $menu_order = $wpdb->get_var($wpdb->prepare("SELECT menu_order FROM $wpdb->posts WHERE ID = %d", $product_id ) );
2998
+
2999
+ $trid = $sitepress->get_element_trid($product_id, 'post_product');
3000
  $translations = $sitepress->get_element_translations($trid, 'post_product');
3001
 
3002
  foreach ($translations as $translation) {
3003
 
3004
+ if ($translation->element_id != $product_id) {
3005
+ $wpdb->update( $wpdb->posts, array('menu_order' => $menu_order), array('ID' => $translation->element_id));
 
3006
  }
3007
  }
3008
  }
3009
+
3010
  }
3011
  }
3012
 
inc/store-pages.class.php CHANGED
@@ -182,19 +182,11 @@ class WCML_Store_Pages{
182
 
183
  if (
184
  !empty($this->shop_page) &&
 
185
  !empty($this->front_page_id) &&
186
  $q->get('post_type') != 'product' &&
187
- ( $q->get('page_id') !== $this->front_page_id &&
188
- (
189
- $this->shop_page_id == $q->get('page_id') ||
190
- (
191
- isset($q->is_home) &&
192
- $q->is_home &&
193
- isset($q->is_posts_page) &&
194
- !$q->is_posts_page
195
- )
196
- )
197
- )
198
  ){
199
  $q->set( 'post_type', 'product' );
200
  $q->set( 'page_id', '' );
182
 
183
  if (
184
  !empty($this->shop_page) &&
185
+ $this->shop_page->post_status == 'publish' &&
186
  !empty($this->front_page_id) &&
187
  $q->get('post_type') != 'product' &&
188
+ $q->get('page_id') !== $this->front_page_id &&
189
+ $this->shop_page_id == $q->get('page_id')
 
 
 
 
 
 
 
 
 
190
  ){
191
  $q->set( 'post_type', 'product' );
192
  $q->set( 'page_id', '' );
inc/terms.class.php CHANGED
@@ -8,6 +8,9 @@ class WCML_Terms{
8
 
9
  private $_tmp_locale_val = false;
10
 
 
 
 
11
  function __construct(){
12
 
13
  add_action('init', array($this, 'init'));
@@ -294,25 +297,38 @@ class WCML_Terms{
294
 
295
  function get_translation_from_woocommerce_mo_file( $string, $language ){
296
  global $sitepress;
 
 
 
 
297
 
298
- $mo = new MO();
299
- $mo_file = WP_LANG_DIR . '/plugins/woocommerce-' . $sitepress->get_locale( $language ) . '.mo';
300
- if( !file_exists( $mo_file ) ){
301
- return $string;
302
- }
303
-
304
- $mo->import_from_file( $mo_file );
305
- $translations = $mo->entries;
306
-
307
- if( in_array( $string, array( 'product','product-category','product-tag' ) ) ){
308
- $string = 'slug'. chr(4) .$string;
309
- }
310
-
311
- if( isset( $translations[$string] ) ){
312
- return $translations[$string]->translations[0];
 
 
 
 
 
 
 
 
 
313
  }
314
 
315
- return $string;
316
 
317
  }
318
 
8
 
9
  private $_tmp_locale_val = false;
10
 
11
+ private $translations_from_mo_file = array();
12
+ private $mo_files = array();
13
+
14
  function __construct(){
15
 
16
  add_action('init', array($this, 'init'));
297
 
298
  function get_translation_from_woocommerce_mo_file( $string, $language ){
299
  global $sitepress;
300
+
301
+ $original_string = $string;
302
+
303
+ if ( ! isset( $this->translations_from_mo_file[ $original_string ][ $language ] ) ) {
304
 
305
+ if ( ! isset( $this->translations_from_mo_file[ $original_string ] ) ) {
306
+ $this->translations_from_mo_file[ $original_string ] = array();
307
+ }
308
+
309
+ if ( ! isset( $this->mo_files[ $language ] ) ) {
310
+ $mo = new MO();
311
+ $mo_file = WP_LANG_DIR . '/plugins/woocommerce-' . $sitepress->get_locale( $language ) . '.mo';
312
+ if( !file_exists( $mo_file ) ){
313
+ return $string;
314
+ }
315
+
316
+ $mo->import_from_file( $mo_file );
317
+ $this->mo_files[ $language ] = &$mo->entries;
318
+ }
319
+
320
+ if( in_array( $string, array( 'product','product-category','product-tag' ) ) ){
321
+ $string = 'slug'. chr(4) .$string;
322
+ }
323
+
324
+ if( isset( $this->mo_files[ $language ][$string] ) ){
325
+ $this->translations_from_mo_file[ $original_string ][ $language ] = $this->mo_files[ $language ][$string]->translations[0];
326
+ } else {
327
+ $this->translations_from_mo_file[ $original_string ][ $language ] = $original_string;
328
+ }
329
  }
330
 
331
+ return $this->translations_from_mo_file[ $original_string ][ $language ];
332
 
333
  }
334
 
inc/wc-strings.class.php CHANGED
@@ -493,7 +493,11 @@ class WCML_WC_Strings{
493
  }else{
494
  global $sitepress_settings;
495
 
496
- return $sitepress_settings['st']['strings_language'];
 
 
 
 
497
  }
498
 
499
  }
@@ -512,11 +516,16 @@ class WCML_WC_Strings{
512
  $orig_shop_page = get_post( apply_filters( 'translate_object_id', $shop_page_id, 'page', true, $this->get_wc_context_language() ) );
513
 
514
  // If permalinks contain the shop page in the URI prepend the breadcrumb with shop
 
515
  if ( $shop_page_id && $orig_shop_page && strstr( $permalinks['product_base'], '/' . $orig_shop_page->post_name ) && get_option( 'page_on_front' ) != $shop_page_id ) {
516
  $breadcrumbs_buff = array();
517
- $i =0;
518
  foreach( $breadcrumbs as $key => $breadcrumb ){
519
- $breadcrumbs_buff[ $i ] = $breadcrumb;
 
 
 
 
520
  if( $key === 0 ){
521
  $i++;
522
  $breadcrumbs_buff[ $i ] = array( get_the_title( $shop_page_id ), get_permalink( $shop_page_id ) );
@@ -525,6 +534,8 @@ class WCML_WC_Strings{
525
  }
526
  $breadcrumbs = $breadcrumbs_buff;
527
  }
 
 
528
  }
529
 
530
  return $breadcrumbs;
493
  }else{
494
  global $sitepress_settings;
495
 
496
+ if ( isset($sitepress_settings['st']['strings_language']) ){
497
+ return $sitepress_settings['st']['strings_language'];
498
+ }
499
+
500
+ return false;
501
  }
502
 
503
  }
516
  $orig_shop_page = get_post( apply_filters( 'translate_object_id', $shop_page_id, 'page', true, $this->get_wc_context_language() ) );
517
 
518
  // If permalinks contain the shop page in the URI prepend the breadcrumb with shop
519
+ // Similar to WC_Breadcrumb::prepend_shop_page
520
  if ( $shop_page_id && $orig_shop_page && strstr( $permalinks['product_base'], '/' . $orig_shop_page->post_name ) && get_option( 'page_on_front' ) != $shop_page_id ) {
521
  $breadcrumbs_buff = array();
522
+ $i = 0;
523
  foreach( $breadcrumbs as $key => $breadcrumb ){
524
+
525
+ if( !in_array( $breadcrumb, $breadcrumbs_buff ) ){
526
+ $breadcrumbs_buff[ $i ] = $breadcrumb;
527
+ }
528
+
529
  if( $key === 0 ){
530
  $i++;
531
  $breadcrumbs_buff[ $i ] = array( get_the_title( $shop_page_id ), get_permalink( $shop_page_id ) );
534
  }
535
  $breadcrumbs = $breadcrumbs_buff;
536
  }
537
+
538
+
539
  }
540
 
541
  return $breadcrumbs;
menu/sub/custom-prices.php CHANGED
@@ -32,8 +32,8 @@ $currencies = $woocommerce_wpml->multi_currency_support->get_currencies();
32
  <input type="radio" name="_wcml_custom_prices[<?php echo $post_id ?>]" value="1" id="wcml_custom_prices_manually[<?php echo $post_id ?>]" class="wcml_custom_prices_input" <?php echo $checked ?> />
33
  <label for="wcml_custom_prices_manually[<?php echo $post_id ?>]"><?php _e('Set prices in other currencies manually','wpml-wcml') ?></label>
34
  <div class="wcml_custom_prices_manually_block_control">
35
- <a href="javascript:void(0);" class="wcml_custom_prices_manually_block_show">&raquo; <?php _e('Enter prices in other currencies','wpml-wcml') ?></a>
36
- <a href="javascript:void(0);" class="wcml_custom_prices_manually_block_hide">- <?php _e('Hide prices in other currencies','wpml-wcml') ?></a>
37
  </div>
38
  </div>
39
 
32
  <input type="radio" name="_wcml_custom_prices[<?php echo $post_id ?>]" value="1" id="wcml_custom_prices_manually[<?php echo $post_id ?>]" class="wcml_custom_prices_input" <?php echo $checked ?> />
33
  <label for="wcml_custom_prices_manually[<?php echo $post_id ?>]"><?php _e('Set prices in other currencies manually','wpml-wcml') ?></label>
34
  <div class="wcml_custom_prices_manually_block_control">
35
+ <a <?php if(!trim($checked)): ?>style="display:none"<?php endif ?> href="javascript:void(0);" class="wcml_custom_prices_manually_block_show">&raquo; <?php _e('Enter prices in other currencies','wpml-wcml') ?></a>
36
+ <a style="display:none" href="javascript:void(0);" class="wcml_custom_prices_manually_block_hide">- <?php _e('Hide prices in other currencies','wpml-wcml') ?></a>
37
  </div>
38
  </div>
39
 
readme.txt CHANGED
@@ -5,7 +5,7 @@ Tags: CMS, woocommerce, commerce, ecommerce, e-commerce, products, WPML, multili
5
  License: GPLv2
6
  Requires at least: 3.0
7
  Tested up to: 4.3
8
- Stable tag: 3.6.9
9
 
10
  Allows running fully multilingual e-commerce sites using WooCommerce and WPML.
11
 
@@ -78,6 +78,17 @@ In order for the checkout and store pages to appear translated, you need to crea
78
 
79
  == Changelog ==
80
 
 
 
 
 
 
 
 
 
 
 
 
81
  = 3.6.9 =
82
  * Bug fix: Prices for variable products were not converted correctly when using multiple currencies after the WooCommerce 2.4 update
83
  * Bug fix: Variations translations were not created when using custom attributes with space characters in them
5
  License: GPLv2
6
  Requires at least: 3.0
7
  Tested up to: 4.3
8
+ Stable tag: 3.6.10
9
 
10
  Allows running fully multilingual e-commerce sites using WooCommerce and WPML.
11
 
78
 
79
  == Changelog ==
80
 
81
+ = 3.6.10 =
82
+ * Bug fix: Custom prices for variations were not saved when clicking the 'Save changes' button
83
+ * Bug fix: Pagination was not working for a category having the term id equal to the id of the account page
84
+ * Bug fix: 'Shop' was appearing two times in the breadcrumbs when using the shop base + category for a product url base
85
+ * Bug fix: Fixed one issue with WooCommerce Bookings - adding two separate bookings to the cart showed as one item instead of two
86
+ * Bug fix: The products menu order was not synced in some situations
87
+ * Fixed a compatibility issue with the Peddlar theme
88
+ * Fixed a styling issue on the custom prices section for product variations
89
+ * Updates for the compatibility with WooCommerce Product Bundles from the plugin author
90
+ * Bug fix: Sometimes it was not possible to enable the slug translation for a custom post when WooCommerce Multilingual was active
91
+
92
  = 3.6.9 =
93
  * Bug fix: Prices for variable products were not converted correctly when using multiple currencies after the WooCommerce 2.4 update
94
  * Bug fix: Variations translations were not created when using custom attributes with space characters in them
woocommerce_wpml.class.php CHANGED
@@ -45,15 +45,15 @@ class woocommerce_wpml {
45
  add_shortcode('currency_switcher', '__return_empty_string');
46
  }
47
 
48
- $this->endpoints = new WCML_Endpoints;
49
- $this->products = new WCML_Products;
50
- $this->store = new WCML_Store_Pages;
51
- $this->emails = new WCML_Emails;
52
- $this->terms = new WCML_Terms;
53
- $this->orders = new WCML_Orders;
54
- $this->troubleshooting = new WCML_Troubleshooting();
55
- $this->compatibility = new WCML_Compatibility();
56
- $this->strings = new WCML_WC_Strings;
57
  $this->currency_switcher = new WCML_CurrencySwitcher;
58
  $this->xdomain_data = new xDomain_Data;
59
 
@@ -136,7 +136,7 @@ class woocommerce_wpml {
136
  }
137
 
138
  function translate_product_slug(){
139
- global $sitepress, $wpdb,$woocommerce, $sitepress_settings;
140
 
141
  if(!defined('WOOCOMMERCE_VERSION') || (!isset($GLOBALS['ICL_Pro_Translation']) || is_null($GLOBALS['ICL_Pro_Translation']))){
142
  return;
@@ -147,19 +147,19 @@ class woocommerce_wpml {
147
  if ( apply_filters( 'wpml_slug_translation_available', false) ) {
148
  // Use new API for WPML >= 3.2.3
149
  do_action( 'wpml_activate_slug_translation', $slug );
150
-
151
  } else {
152
  // Pre WPML 3.2.3
153
  $string = $wpdb->get_row($wpdb->prepare("SELECT id,status FROM {$wpdb->prefix}icl_strings WHERE name = %s AND value = %s ", 'URL slug: ' . $slug, $slug));
154
-
155
  if(!$string){
156
  do_action('wpml_register_single_string', 'WordPress', 'URL slug: ' . $slug, $slug);
157
  $string = $wpdb->get_row($wpdb->prepare("SELECT id,status FROM {$wpdb->prefix}icl_strings WHERE name = %s AND value = %s ", 'URL slug: ' . $slug, $slug));
158
  }
159
 
160
  }
161
-
162
- if(empty($sitepress_settings['posts_slug_translation']['on']) || empty($sitepress_settings['posts_slug_translation']['types']['product'])){
163
  $iclsettings['posts_slug_translation']['on'] = 1;
164
  $iclsettings['posts_slug_translation']['types']['product'] = 1;
165
  $sitepress->save_settings($iclsettings);
@@ -789,7 +789,7 @@ class woocommerce_wpml {
789
  $notices = maybe_unserialize( get_option( 'wcml_translations_upgrade_notice' ) );
790
 
791
  if ( 'en_US' !== $locale && ( ! is_array( $version ) || version_compare( $version[0], WC_VERSION, '<' ) || $version[1] !== $locale ) ) {
792
- if ( $wc_upgrader_class->check_if_language_pack_exists() ) {
793
 
794
  if( !$notices || !in_array( $locale, $notices )){
795
  $notices[] = $locale;
45
  add_shortcode('currency_switcher', '__return_empty_string');
46
  }
47
 
48
+ $this->endpoints = new WCML_Endpoints;
49
+ $this->products = new WCML_Products;
50
+ $this->store = new WCML_Store_Pages;
51
+ $this->emails = new WCML_Emails( $sitepress );
52
+ $this->terms = new WCML_Terms;
53
+ $this->orders = new WCML_Orders;
54
+ $this->troubleshooting = new WCML_Troubleshooting();
55
+ $this->compatibility = new WCML_Compatibility();
56
+ $this->strings = new WCML_WC_Strings;
57
  $this->currency_switcher = new WCML_CurrencySwitcher;
58
  $this->xdomain_data = new xDomain_Data;
59
 
136
  }
137
 
138
  function translate_product_slug(){
139
+ global $sitepress, $wpdb, $woocommerce;
140
 
141
  if(!defined('WOOCOMMERCE_VERSION') || (!isset($GLOBALS['ICL_Pro_Translation']) || is_null($GLOBALS['ICL_Pro_Translation']))){
142
  return;
147
  if ( apply_filters( 'wpml_slug_translation_available', false) ) {
148
  // Use new API for WPML >= 3.2.3
149
  do_action( 'wpml_activate_slug_translation', $slug );
150
+
151
  } else {
152
  // Pre WPML 3.2.3
153
  $string = $wpdb->get_row($wpdb->prepare("SELECT id,status FROM {$wpdb->prefix}icl_strings WHERE name = %s AND value = %s ", 'URL slug: ' . $slug, $slug));
154
+
155
  if(!$string){
156
  do_action('wpml_register_single_string', 'WordPress', 'URL slug: ' . $slug, $slug);
157
  $string = $wpdb->get_row($wpdb->prepare("SELECT id,status FROM {$wpdb->prefix}icl_strings WHERE name = %s AND value = %s ", 'URL slug: ' . $slug, $slug));
158
  }
159
 
160
  }
161
+ $iclsettings = $sitepress->get_settings();
162
+ if(empty($iclsettings['posts_slug_translation']['on']) || empty($iclsettings['posts_slug_translation']['types']['product'])){
163
  $iclsettings['posts_slug_translation']['on'] = 1;
164
  $iclsettings['posts_slug_translation']['types']['product'] = 1;
165
  $sitepress->save_settings($iclsettings);
789
  $notices = maybe_unserialize( get_option( 'wcml_translations_upgrade_notice' ) );
790
 
791
  if ( 'en_US' !== $locale && ( ! is_array( $version ) || version_compare( $version[0], WC_VERSION, '<' ) || $version[1] !== $locale ) ) {
792
+ if ( $wc_upgrader_class->check_if_language_pack_exists( $locale ) ) {
793
 
794
  if( !$notices || !in_array( $locale, $notices )){
795
  $notices[] = $locale;
wpml-woocommerce.php CHANGED
@@ -5,12 +5,12 @@
5
  Description: Allows running fully multilingual e-Commerce sites with WooCommerce and WPML. <a href="http://wpml.org/documentation/related-projects/woocommerce-multilingual/">Documentation</a>.
6
  Author: OnTheGoSystems
7
  Author URI: http://www.onthegosystems.com/
8
- Version: 3.6.9
9
  */
10
 
11
 
12
  if(defined('WCML_VERSION')) return;
13
- define('WCML_VERSION', '3.6.9');
14
  define('WCML_PLUGIN_PATH', dirname(__FILE__));
15
  define('WCML_PLUGIN_FOLDER', basename(WCML_PLUGIN_PATH));
16
  define('WCML_PLUGIN_URL', plugins_url() . '/' . WCML_PLUGIN_FOLDER);
5
  Description: Allows running fully multilingual e-Commerce sites with WooCommerce and WPML. <a href="http://wpml.org/documentation/related-projects/woocommerce-multilingual/">Documentation</a>.
6
  Author: OnTheGoSystems
7
  Author URI: http://www.onthegosystems.com/
8
+ Version: 3.6.10
9
  */
10
 
11
 
12
  if(defined('WCML_VERSION')) return;
13
+ define('WCML_VERSION', '3.6.10');
14
  define('WCML_PLUGIN_PATH', dirname(__FILE__));
15
  define('WCML_PLUGIN_FOLDER', basename(WCML_PLUGIN_PATH));
16
  define('WCML_PLUGIN_URL', plugins_url() . '/' . WCML_PLUGIN_FOLDER);