WooCommerce Multilingual – run WooCommerce with WPML - Version 4.1.3

Version Description

  • Improvements for the REST API support (compliant with WooCommerce REST API v2)
  • Bug fix: Order confirmation emails were not translated correctly when using WooCommerce 3.0
  • Bug fix: The admin language switcher was displayed in a wrong place when using the Swish
  • Bug fix: Composite products were displaying the wrong price amount in secondary currencies
  • Bug fix: Sometimes switching the currency on the front end didn't work when using a caching plugin
  • Bug fix: Don't enforce the REST API support (added in 4.1) for legacy WooCommerce REST calls
  • Bug fix: In some conditions, variations custom fields were double-serialized when copied to the translations
  • Bug fix: Sometimes the currency switcher preview was not displaying correctly
  • Bug fix: Manually adding a product to an order was sometimes causing a fatal error
  • Bug fix: A fatal error was occurring when trying to translate a bookable product with Persons
  • Bug fix: The RTL styles were loaded incorrectly on the translation management when Yoast SEO was active
  • Bug fix: Trying to display the currency switcher with the 'do_action' function was causing a fatal error
  • Bug fix: Product urls were incorrect when permalink structure was set to /index.php/%postname%/
  • Bug fix: Product variation custom fields were double-serialized when copied to translations
  • Bug fix: Language switcher was misplaced when using the Swish Gateway extension
  • Bug fix: Downloadable files were not available in secondary languages
  • Bug fix: Using The Events Calendar without Tribe Tickets RSVP and Tribe Tickets Plus caused errors
  • Bug fix: Incorrect currency was shown in the backend for orders placed in a secondary currency
  • Bug fix: In some circumstances, the shipping tax was rounded incorrectly in the secondary currencies
  • Bug fix: After duplicating a variable product, the variations weren't showing on the translated product edit page
  • Added the option to synchronize the products stock information on the troubleshooting section
  • Fixed a compatibility issue with WooCommerce Bookings and WooCommerce Product addons (both active)
  • Fixed a compatibility issue with WooCommerce Subscriptions (shipping costs incorrectly displayed)
  • Fixed a compatibility issue with WooCommerce Product Bundles (removed items were not synced with translations)
  • Fixed a compatibility issue with WooCommerce Membership
  • Fixed a compatibility issue with WooCommerce Print Invoices/Packing Lists (PHP notices and possible a fatal error)
  • Fixed compatibility issues with Aelia Currency Switcher and Aelia Foundation
  • Fixed a compatibility issue with Visual Composer: shortcodes were not parsed in the translation editor
Download this release

Release Info

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

Code changes from version 4.1.2 to 4.1.3

Files changed (78) hide show
  1. compatibility/class-wcml-accommodation-bookings.php +8 -3
  2. compatibility/class-wcml-adventure-tours.php +2 -4
  3. compatibility/class-wcml-bookings.php +32 -11
  4. compatibility/class-wcml-composite-products.php +68 -0
  5. compatibility/class-wcml-klarna-gateway.php +18 -0
  6. compatibility/class-wcml-mix-and-match-products.php +1 -2
  7. compatibility/class-wcml-pip.php +3 -2
  8. compatibility/class-wcml-product-addons.php +21 -0
  9. compatibility/class-wcml-product-bundles.php +40 -11
  10. compatibility/class-wcml-table-rate-shipping.php +1 -1
  11. compatibility/class-wcml-the-events-calendar.php +4 -4
  12. compatibility/class-wcml-wc-memberships.php +84 -0
  13. compatibility/class-wcml-wc-subscriptions.php +183 -160
  14. compatibility/class-wcml-wcexporter.php +1 -1
  15. compatibility/class-wcml-yith-wcqv.php +18 -0
  16. compatibility/includes/class-wcml-wc-product-bundles-items.php +6 -1
  17. compatibility/res/js/wcml-members.js +19 -0
  18. inc/abstracts/class-wcml-exchange-rate-service.php +1 -1
  19. inc/admin-menus/class-wcml-admin-menus.php +3 -2
  20. inc/admin-menus/class-wcml-taxonomy-translation-link-filters.php +102 -0
  21. inc/class-wcml-attributes.php +1 -1
  22. inc/class-wcml-cart.php +13 -5
  23. inc/class-wcml-compatibility.php +18 -0
  24. inc/class-wcml-dependencies.php +1 -1
  25. inc/class-wcml-emails.php +43 -26
  26. inc/class-wcml-endpoints.php +12 -3
  27. inc/class-wcml-install.php +1 -1
  28. inc/class-wcml-orders.php +37 -0
  29. inc/class-wcml-products.php +21 -0
  30. inc/class-wcml-resources.php +20 -18
  31. inc/class-wcml-troubleshooting.php +105 -54
  32. inc/class-wcml-upgrade.php +1 -1
  33. inc/class-wcml-url-translation.php +649 -600
  34. inc/class-wcml-wc-gateways.php +5 -8
  35. inc/class-wcml-wc-shipping.php +23 -12
  36. inc/class-wcml-wc-strings.php +1 -1
  37. inc/class-woocommerce-wpml.php +23 -5
  38. inc/currencies/class-wcml-custom-prices.php +3 -4
  39. inc/currencies/class-wcml-multi-currency-orders.php +7 -6
  40. inc/currencies/class-wcml-multi-currency-prices.php +31 -37
  41. inc/currencies/class-wcml-multi-currency-resources.php +0 -2
  42. inc/currencies/class-wcml-multi-currency-shipping.php +2 -6
  43. inc/currencies/class-wcml-multi-currency.php +8 -8
  44. inc/currencies/currency-switcher/class-wcml-currency-switcher-ajax.php +2 -1
  45. inc/currencies/currency-switcher/class-wcml-currency-switcher-templates.php +23 -1
  46. inc/currencies/currency-switcher/class-wcml-currency-switcher.php +38 -4
  47. inc/rest-api-support/class-wcml-rest-api-support-v1.php +397 -0
  48. inc/rest-api-support/class-wcml-rest-api-support.php +439 -0
  49. inc/template-classes/class-wcml-menus-wrap.php +1 -1
  50. inc/template-classes/class-wcml-plugins-wrap.php +2 -2
  51. inc/template-classes/class-wcml-products-ui.php +20 -12
  52. inc/template-classes/class-wcml-troubleshooting-ui.php +3 -0
  53. inc/template-classes/status/class-wcml-status-status-ui.php +1 -1
  54. inc/translation-editor/class-wcml-editor-ui-product-job.php +27 -5
  55. inc/translation-editor/class-wcml-page-builders.php +107 -0
  56. inc/translation-editor/class-wcml-synchronize-product-data.php +2 -80
  57. inc/translation-editor/class-wcml-synchronize-variations-data.php +1 -1
  58. inc/translation-editor/class-wcml-translation-editor.php +1 -2
  59. inc/translation-editor/class-wcml-wc-admin-duplicate-product.php +118 -0
  60. inc/woocommerce-functions-wrapper.php +17 -1
  61. readme.txt +32 -1
  62. res/js/dialogs.js +7 -6
  63. res/js/dialogs.min.js +1 -1
  64. res/js/troubleshooting.js +209 -200
  65. res/js/troubleshooting.min.js +1 -1
  66. res/js/wcml-multi-currency.js +1 -2
  67. res/js/wcml-multi-currency.min.js +1 -1
  68. templates/plugins-wrap.twig +16 -16
  69. templates/troubleshooting.twig +13 -1
  70. vendor/autoload.php +1 -1
  71. vendor/autoload_52.php +1 -1
  72. vendor/composer/ClassLoader.php +7 -3
  73. vendor/composer/LICENSE +1 -1
  74. vendor/composer/autoload_classmap.php +8 -1
  75. vendor/composer/autoload_real.php +4 -4
  76. vendor/composer/autoload_real_52.php +3 -3
  77. vendor/composer/autoload_static.php +13 -6
  78. wpml-woocommerce.php +7 -5
compatibility/class-wcml-accommodation-bookings.php CHANGED
@@ -35,7 +35,13 @@ class WCML_Accommodation_Bookings{
35
 
36
  function after_bookings_pricing( $post_id ){
37
 
38
- if( $this->woocommerce_wpml->products->is_original_product( $post_id ) && $this->woocommerce_wpml->settings['enable_multi_currency'] == WCML_MULTI_CURRENCIES_INDEPENDENT ){
 
 
 
 
 
 
39
 
40
  $custom_costs_status = get_post_meta( $post_id, '_wcml_custom_costs_status', true );
41
 
@@ -159,8 +165,7 @@ class WCML_Accommodation_Bookings{
159
 
160
  remove_filter( 'get_post_metadata', array( $this, 'product_price_filter' ), 9, 4 );
161
 
162
- $original_language = $this->woocommerce_wpml->products->get_original_product_language( $object_id );
163
- $original_product = apply_filters( 'translate_object_id', $object_id, 'product', true, $original_language );
164
 
165
  if ( get_post_meta( $original_product, '_wcml_custom_costs_status' ) ) {
166
 
35
 
36
  function after_bookings_pricing( $post_id ){
37
 
38
+ $product_terms = wp_get_post_terms( $post_id, 'product_type', array( "fields" => "names" ) );
39
+
40
+ if(
41
+ in_array( 'accommodation-booking', $product_terms ) &&
42
+ $this->woocommerce_wpml->products->is_original_product( $post_id ) &&
43
+ $this->woocommerce_wpml->settings['enable_multi_currency'] == WCML_MULTI_CURRENCIES_INDEPENDENT
44
+ ){
45
 
46
  $custom_costs_status = get_post_meta( $post_id, '_wcml_custom_costs_status', true );
47
 
165
 
166
  remove_filter( 'get_post_metadata', array( $this, 'product_price_filter' ), 9, 4 );
167
 
168
+ $original_product = $this->woocommerce_wpml->products->get_original_product_id( $object_id );
 
169
 
170
  if ( get_post_meta( $original_product, '_wcml_custom_costs_status' ) ) {
171
 
compatibility/class-wcml-adventure-tours.php CHANGED
@@ -55,8 +55,7 @@ class WCML_Adventure_tours{
55
 
56
  } else {
57
 
58
- $original_product_language = $woocommerce_wpml->products->get_original_product_language( $post_id );
59
- $original_product_id = apply_filters( 'translate_object_id', $post_id, 'product', true, $original_product_language);
60
 
61
  }
62
 
@@ -308,8 +307,7 @@ class WCML_Adventure_tours{
308
 
309
  remove_filter( 'get_post_metadata', array( $this, 'product_price_filter' ), 9, 4 );
310
 
311
- $original_language = $woocommerce_wpml->products->get_original_product_language( $object_id );
312
- $original_product = apply_filters( 'translate_object_id', $object_id, 'product', true, $original_language );
313
 
314
  if ( get_post_meta( $original_product, '_wcml_custom_prices_status' ) ) {
315
  $custom_periods_prices = get_post_meta( $object_id, 'custom_booking_periods_prices', true );
55
 
56
  } else {
57
 
58
+ $original_product_id = $this->woocommerce_wpml->products->get_original_product_id( $post_id );
 
59
 
60
  }
61
 
307
 
308
  remove_filter( 'get_post_metadata', array( $this, 'product_price_filter' ), 9, 4 );
309
 
310
+ $original_product = $this->woocommerce_wpml->products->get_original_product_id( $object_id );
 
311
 
312
  if ( get_post_meta( $original_product, '_wcml_custom_prices_status' ) ) {
313
  $custom_periods_prices = get_post_meta( $object_id, 'custom_booking_periods_prices', true );
compatibility/class-wcml-bookings.php CHANGED
@@ -751,7 +751,7 @@ class WCML_Bookings {
751
 
752
  if ( $this->woocommerce_wpml->settings['enable_multi_currency'] == WCML_MULTI_CURRENCIES_INDEPENDENT ) {
753
 
754
- $original_id = apply_filters( 'translate_object_id', $object_id, 'product', true, $this->woocommerce_wpml->products->get_original_product_language( $object_id ) );
755
 
756
  $cost_status = get_post_meta( $original_id, '_wcml_custom_costs_status', true );
757
 
@@ -874,7 +874,7 @@ class WCML_Bookings {
874
  function sync_resource_costs_with_translations( $object_id, $meta_key, $check = false ) {
875
 
876
 
877
- $original_product_id = apply_filters( 'translate_object_id', $object_id, 'product', true, $this->woocommerce_wpml->products->get_original_product_language( $object_id ) );
878
 
879
  if ( $object_id == $original_product_id ) {
880
 
@@ -976,7 +976,7 @@ class WCML_Bookings {
976
  }
977
 
978
  if ( isset( $booking_id ) ) {
979
- $original_id = apply_filters( 'translate_object_id', $booking_id, 'product', true, $this->woocommerce_wpml->products->get_original_product_language( $booking_id ) );
980
 
981
  if ( $booking_id != $original_id ) {
982
  $fields = maybe_unserialize( get_post_meta( $original_id, '_wc_booking_pricing', true ) );
@@ -984,10 +984,14 @@ class WCML_Bookings {
984
  }
985
  }
986
 
987
- if ( isset( $fields[ $name . $currency ] ) ) {
988
- return $fields[ $name . $currency ];
989
- } else {
990
- return $this->woocommerce_wpml->multi_currency->prices->convert_price_amount( $cost, $currency );
 
 
 
 
991
  }
992
 
993
  }
@@ -996,6 +1000,21 @@ class WCML_Bookings {
996
 
997
  }
998
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
999
  function load_assets( $external_product_type = false ) {
1000
  global $pagenow;
1001
 
@@ -1788,15 +1807,17 @@ class WCML_Bookings {
1788
 
1789
  foreach ( $person_types as $person_type ) {
1790
 
1791
- $package['contents'][ 'wc_bookings:person:' . $person_type->ID . ':name' ] = array(
 
 
1792
  'translate' => 1,
1793
- 'data' => $this->tp->encode_field_data( $person_type->get_name(), 'base64' ),
1794
  'format' => 'base64'
1795
  );
1796
 
1797
- $package['contents'][ 'wc_bookings:person:' . $person_type->ID . ':description' ] = array(
1798
  'translate' => 1,
1799
- 'data' => $this->tp->encode_field_data( $person_type->get_description(), 'base64' ),
1800
  'format' => 'base64'
1801
  );
1802
 
751
 
752
  if ( $this->woocommerce_wpml->settings['enable_multi_currency'] == WCML_MULTI_CURRENCIES_INDEPENDENT ) {
753
 
754
+ $original_id = $this->woocommerce_wpml->products->get_original_product_id( $object_id );
755
 
756
  $cost_status = get_post_meta( $original_id, '_wcml_custom_costs_status', true );
757
 
874
  function sync_resource_costs_with_translations( $object_id, $meta_key, $check = false ) {
875
 
876
 
877
+ $original_product_id = $this->woocommerce_wpml->products->get_original_product_id( $object_id );
878
 
879
  if ( $object_id == $original_product_id ) {
880
 
976
  }
977
 
978
  if ( isset( $booking_id ) ) {
979
+ $original_id = $this->woocommerce_wpml->products->get_original_product_id( $booking_id );
980
 
981
  if ( $booking_id != $original_id ) {
982
  $fields = maybe_unserialize( get_post_meta( $original_id, '_wc_booking_pricing', true ) );
984
  }
985
  }
986
 
987
+ $needs_filter_pricing_cost = $this->needs_filter_pricing_cost( $name, $fields );
988
+
989
+ if( $needs_filter_pricing_cost ){
990
+ if ( isset( $fields[ $name . $currency ] ) ) {
991
+ return $fields[ $name . $currency ];
992
+ } else {
993
+ return $this->woocommerce_wpml->multi_currency->prices->convert_price_amount( $cost, $currency );
994
+ }
995
  }
996
 
997
  }
1000
 
1001
  }
1002
 
1003
+ function needs_filter_pricing_cost( $name, $fields ){
1004
+
1005
+ $modifier_skip_values = array( 'divide', 'times' );
1006
+
1007
+ if(
1008
+ 'override_block_' === $name ||
1009
+ ( 'cost_' === $name && !in_array( $fields[ 'modifier' ], $modifier_skip_values ) ) ||
1010
+ ( 'base_cost_' === $name && !in_array( $fields[ 'base_modifier' ], $modifier_skip_values ) )
1011
+ ){
1012
+ return true;
1013
+ }else{
1014
+ return false;
1015
+ }
1016
+ }
1017
+
1018
  function load_assets( $external_product_type = false ) {
1019
  global $pagenow;
1020
 
1807
 
1808
  foreach ( $person_types as $person_type ) {
1809
 
1810
+ $bookable_person = get_post( $person_type->ID );
1811
+
1812
+ $package['contents'][ 'wc_bookings:person:' . $bookable_person->ID . ':name' ] = array(
1813
  'translate' => 1,
1814
+ 'data' => $this->tp->encode_field_data( $bookable_person->post_title, 'base64' ),
1815
  'format' => 'base64'
1816
  );
1817
 
1818
+ $package['contents'][ 'wc_bookings:person:' . $bookable_person->ID . ':description' ] = array(
1819
  'translate' => 1,
1820
+ 'data' => $this->tp->encode_field_data( $bookable_person->post_excerpt, 'base64' ),
1821
  'format' => 'base64'
1822
  );
1823
 
compatibility/class-wcml-composite-products.php CHANGED
@@ -40,7 +40,12 @@ class WCML_Composite_Products extends WCML_Compatibility_Helper{
40
  add_filter( 'wcml_js_lock_fields_ids', array( $this, 'wcml_js_lock_fields_ids' ) );
41
  add_filter( 'wcml_after_load_lock_fields_js', array( $this, 'localize_lock_fields_js' ) );
42
  add_action( 'init', array( $this, 'load_assets' ) );
 
 
 
 
43
  }
 
44
  }
45
 
46
  function woocommerce_composite_component_default_option($selected_value, $component_id, $object) {
@@ -476,4 +481,67 @@ class WCML_Composite_Products extends WCML_Compatibility_Helper{
476
  return get_post_meta( $product_id, '_bto_data', true );
477
  }
478
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
479
  }
40
  add_filter( 'wcml_js_lock_fields_ids', array( $this, 'wcml_js_lock_fields_ids' ) );
41
  add_filter( 'wcml_after_load_lock_fields_js', array( $this, 'localize_lock_fields_js' ) );
42
  add_action( 'init', array( $this, 'load_assets' ) );
43
+
44
+ add_action( 'wcml_after_save_custom_prices', array( $this, 'update_composite_custom_prices' ), 10, 4 );
45
+ }else{
46
+ add_filter( 'get_post_metadata', array( $this, 'filter_composite_product_cost' ), 10, 4 );
47
  }
48
+
49
  }
50
 
51
  function woocommerce_composite_component_default_option($selected_value, $component_id, $object) {
481
  return get_post_meta( $product_id, '_bto_data', true );
482
  }
483
 
484
+
485
+ function filter_composite_product_cost( $value, $object_id, $meta_key, $single ) {
486
+
487
+ if ( in_array( $meta_key, array(
488
+ '_bto_base_regular_price',
489
+ '_bto_base_sale_price',
490
+ '_bto_base_price'
491
+ ) ) ) {
492
+
493
+ if ( $this->woocommerce_wpml->settings['enable_multi_currency'] == WCML_MULTI_CURRENCIES_INDEPENDENT ) {
494
+
495
+ $original_id = $this->woocommerce_wpml->products->get_original_product_id( $object_id );
496
+
497
+ $cost_status = get_post_meta( $original_id, '_wcml_custom_prices_status', true );
498
+
499
+ $currency = $this->woocommerce_wpml->multi_currency->get_client_currency();
500
+
501
+ if ( $currency == get_option( 'woocommerce_currency' ) ) {
502
+ return $value;
503
+ }
504
+
505
+ $cost = get_post_meta( $original_id, $meta_key . '_' . $currency, true );
506
+
507
+ if ( $cost_status && !empty( $cost ) ) {
508
+
509
+ return $cost;
510
+
511
+ } else {
512
+
513
+ remove_filter( 'get_post_metadata', array( $this, 'filter_composite_product_cost' ), 10, 4 );
514
+
515
+ $cost = get_post_meta( $original_id, $meta_key, true );
516
+
517
+ add_filter( 'get_post_metadata', array( $this, 'filter_composite_product_cost' ), 10, 4 );
518
+
519
+ if( $cost ){
520
+
521
+ $cost = $this->woocommerce_wpml->multi_currency->prices->convert_price_amount( $cost, $currency );
522
+
523
+ return $cost;
524
+ }
525
+
526
+ }
527
+
528
+ }
529
+
530
+ }
531
+
532
+ return $value;
533
+ }
534
+
535
+ function update_composite_custom_prices( $product_id, $product_price, $custom_prices, $code ){
536
+
537
+ if( $this->get_product_type( $product_id ) == 'composite' ){
538
+
539
+ update_post_meta( $product_id, '_bto_base_regular_price'.'_'.$code, $custom_prices[ '_regular_price' ] );
540
+ update_post_meta( $product_id, '_bto_base_sale_price'.'_'.$code, $custom_prices[ '_sale_price' ] );
541
+ update_post_meta( $product_id, '_bto_base_price'.'_'.$code, $product_price );
542
+
543
+ }
544
+
545
+ }
546
+
547
  }
compatibility/class-wcml-klarna-gateway.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WCML_Klarna_Gateway{
4
+
5
+ public function add_hooks(){
6
+
7
+ add_filter( 'wcml_multi_currency_ajax_actions', array( $this, 'ajax_action_needs_multi_currency' ) );
8
+
9
+ }
10
+
11
+ function ajax_action_needs_multi_currency( $actions ){
12
+
13
+ $actions[] = 'klarna_checkout_cart_callback_update';
14
+
15
+ return $actions;
16
+ }
17
+
18
+ }
compatibility/class-wcml-mix-and-match-products.php CHANGED
@@ -30,8 +30,7 @@ class WCML_Mix_and_Match_Products{
30
 
31
  } else {
32
 
33
- $original_product_language = $woocommerce_wpml->products->get_original_product_language( $post_id );
34
- $original_product_id = apply_filters( 'translate_object_id', $post_id, 'product', true, $original_product_language );
35
 
36
  }
37
 
30
 
31
  } else {
32
 
33
+ $original_product_id = $this->woocommerce_wpml->products->get_original_product_id( $post_id );
 
34
 
35
  }
36
 
compatibility/class-wcml-pip.php CHANGED
@@ -73,9 +73,10 @@ class WCML_Pip{
73
 
74
  $pip_order_id = $this->get_pip_order_id();
75
 
76
- if( $pip_order_id ){
 
 
77
 
78
- $the_order = new WC_Order( $pip_order_id );
79
  if( $the_order ){
80
  $currency = WooCommerce_Functions_Wrapper::get_order_currency( $the_order );
81
 
73
 
74
  $pip_order_id = $this->get_pip_order_id();
75
 
76
+ if( $pip_order_id && isset( WC()->order_factory ) ){
77
+
78
+ $the_order = WC()->order_factory->get_order( $pip_order_id );
79
 
 
80
  if( $the_order ){
81
  $currency = WooCommerce_Functions_Wrapper::get_order_currency( $the_order );
82
 
compatibility/class-wcml-product-addons.php CHANGED
@@ -43,6 +43,11 @@ class WCML_Product_Addons {
43
 
44
  add_action( 'woocommerce_product_data_panels', array( $this, 'show_pointer_info' ) );
45
  }
 
 
 
 
 
46
  }
47
 
48
  /**
@@ -260,4 +265,20 @@ class WCML_Product_Addons {
260
 
261
  $pointer_ui->show();
262
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
263
  }
43
 
44
  add_action( 'woocommerce_product_data_panels', array( $this, 'show_pointer_info' ) );
45
  }
46
+
47
+ add_filter( 'wcml_cart_contents_not_changed', array(
48
+ $this,
49
+ 'filter_booing_addon_product_in_cart_contents'
50
+ ), 20 );
51
  }
52
 
53
  /**
265
 
266
  $pointer_ui->show();
267
  }
268
+
269
+ // special case for WC Bookings plugin - need add addon cost after re-calculating booking costs #wcml-1877
270
+ public function filter_booing_addon_product_in_cart_contents( $cart_item ) {
271
+
272
+ if ( $cart_item['data'] instanceof WC_Product_Booking && isset( $cart_item['addons'] ) ) {
273
+ $cost = $cart_item['data']->get_price();
274
+
275
+ foreach( $cart_item['addons'] as $addon ){
276
+ $cost += $addon['price'];
277
+ }
278
+
279
+ $cart_item['data']->set_price( $cost );
280
+ }
281
+
282
+ return $cart_item;
283
+ }
284
  }
compatibility/class-wcml-product-bundles.php CHANGED
@@ -46,9 +46,15 @@ class WCML_Product_Bundles{
46
  add_action( 'wcml_after_duplicate_product_post_meta', array( $this, 'sync_bundled_ids' ), 10, 2 );
47
  add_action( 'wcml_update_extra_fields', array( $this, 'bundle_update' ), 10, 4 );
48
 
49
- add_action( 'save_post', array( $this, 'sync_product_bundle_meta_with_translations' ) );
 
50
  }
51
 
 
 
 
 
 
52
  }
53
 
54
  private function get_product_bundle_data( $bundle_id ){
@@ -67,15 +73,12 @@ class WCML_Product_Bundles{
67
  $bundle_items = $this->product_bundles_items->get_items( $bundle_id );
68
 
69
  foreach( $bundle_items as $item_id => $bundle_item ){
70
-
71
  $bundled_item_data = $this->product_bundles_items->get_item_data_object( $item_id );
72
 
73
  foreach( $product_bundle_data[ $item_id ] as $key => $value ){
74
  $this->product_bundles_items->update_item_meta( $bundled_item_data, $key, $value );
75
  }
76
-
77
  $this->product_bundles_items->save_item_meta( $bundled_item_data );
78
-
79
  }
80
 
81
  }
@@ -100,7 +103,7 @@ class WCML_Product_Bundles{
100
  );
101
 
102
  $target_lang = $this->sitepress->get_language_for_element( $translated_bundle_id, 'post_product' );
103
-
104
  foreach( $bundle_items as $item_id => $bundle_item ){
105
 
106
  $item_meta = $this->product_bundles_items->get_item_data( $bundle_item );
@@ -108,17 +111,26 @@ class WCML_Product_Bundles{
108
 
109
  if( $translated_product_id ){
110
  $translated_item_id = $this->get_item_id_for_product_id( $translated_product_id, $translated_bundle_id );
 
111
 
112
  $translated_item = $this->product_bundles_items->get_item_data_object( $translated_item_id );
113
  foreach( $fields_to_sync as $key ){
114
  $this->product_bundles_items->update_item_meta( $translated_item, $key, $item_meta[$key] );
115
  }
116
  $this->product_bundles_items->save_item_meta( $translated_item );
 
117
  }
118
 
119
  }
120
 
121
-
 
 
 
 
 
 
 
122
 
123
  }
124
 
@@ -127,9 +139,9 @@ class WCML_Product_Bundles{
127
  if ( WooCommerce_Functions_Wrapper::get_product_type( $bundle_id ) === 'bundle' ) {
128
 
129
  $trid = $this->sitepress->get_element_trid( $bundle_id, 'post_product' );
130
- $tranlations = $this->sitepress->get_element_translations( $trid, 'post_product' );
131
 
132
- foreach ( $tranlations as $language => $translation ) {
133
  if ( $translation->original ) {
134
  $original_bundle_id = $translation->element_id;
135
  break;
@@ -137,7 +149,7 @@ class WCML_Product_Bundles{
137
 
138
  }
139
 
140
- foreach ( $tranlations as $language => $translation ) {
141
  if ( $translation->element_id !== $original_bundle_id ) {
142
  $this->sync_product_bundle_meta( $original_bundle_id, $translation->element_id );
143
  }
@@ -161,7 +173,6 @@ class WCML_Product_Bundles{
161
  ) );
162
  }
163
 
164
-
165
  // Add Bundles Box to WCML Translation GUI
166
  public function custom_box_html( $obj, $bundle_id, $data ){
167
 
@@ -304,7 +315,7 @@ class WCML_Product_Bundles{
304
 
305
  }
306
 
307
- // Update Bundled products title and descritpion after saving the translation
308
  public function bundle_update( $bundle_id, $translated_bundle_id, $data, $lang ){
309
  global $wpdb;
310
 
@@ -597,4 +608,22 @@ class WCML_Product_Bundles{
597
 
598
  return $wpdb->insert_id;
599
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
600
  }
46
  add_action( 'wcml_after_duplicate_product_post_meta', array( $this, 'sync_bundled_ids' ), 10, 2 );
47
  add_action( 'wcml_update_extra_fields', array( $this, 'bundle_update' ), 10, 4 );
48
 
49
+ add_action( 'wp_insert_post', array( $this, 'sync_product_bundle_meta_with_translations' ), 10 );
50
+
51
  }
52
 
53
+ // product bundle using separate custom fields for prices
54
+ if( wcml_is_multi_currency_on() ){
55
+ add_filter( 'wcml_price_custom_fields_filtered', array( $this, 'get_price_custom_fields' ) );
56
+ }
57
+
58
  }
59
 
60
  private function get_product_bundle_data( $bundle_id ){
73
  $bundle_items = $this->product_bundles_items->get_items( $bundle_id );
74
 
75
  foreach( $bundle_items as $item_id => $bundle_item ){
 
76
  $bundled_item_data = $this->product_bundles_items->get_item_data_object( $item_id );
77
 
78
  foreach( $product_bundle_data[ $item_id ] as $key => $value ){
79
  $this->product_bundles_items->update_item_meta( $bundled_item_data, $key, $value );
80
  }
 
81
  $this->product_bundles_items->save_item_meta( $bundled_item_data );
 
82
  }
83
 
84
  }
103
  );
104
 
105
  $target_lang = $this->sitepress->get_language_for_element( $translated_bundle_id, 'post_product' );
106
+ $translated_item_ids = array();
107
  foreach( $bundle_items as $item_id => $bundle_item ){
108
 
109
  $item_meta = $this->product_bundles_items->get_item_data( $bundle_item );
111
 
112
  if( $translated_product_id ){
113
  $translated_item_id = $this->get_item_id_for_product_id( $translated_product_id, $translated_bundle_id );
114
+ $translated_item_ids[] = $translated_item_id;
115
 
116
  $translated_item = $this->product_bundles_items->get_item_data_object( $translated_item_id );
117
  foreach( $fields_to_sync as $key ){
118
  $this->product_bundles_items->update_item_meta( $translated_item, $key, $item_meta[$key] );
119
  }
120
  $this->product_bundles_items->save_item_meta( $translated_item );
121
+
122
  }
123
 
124
  }
125
 
126
+ // Delete removed items
127
+ $translated_bundle_items = $this->product_bundles_items->get_items( $translated_bundle_id );
128
+ foreach ( $translated_bundle_items as $item_id => $bundle_item ) {
129
+ if ( ! in_array( $item_id, $translated_item_ids ) ) {
130
+ $bundled_item_data = $this->product_bundles_items->get_item_data_object( $item_id );
131
+ $bundled_item_data->delete();
132
+ }
133
+ }
134
 
135
  }
136
 
139
  if ( WooCommerce_Functions_Wrapper::get_product_type( $bundle_id ) === 'bundle' ) {
140
 
141
  $trid = $this->sitepress->get_element_trid( $bundle_id, 'post_product' );
142
+ $translations = $this->sitepress->get_element_translations( $trid, 'post_product' );
143
 
144
+ foreach ( $translations as $language => $translation ) {
145
  if ( $translation->original ) {
146
  $original_bundle_id = $translation->element_id;
147
  break;
149
 
150
  }
151
 
152
+ foreach ( $translations as $language => $translation ) {
153
  if ( $translation->element_id !== $original_bundle_id ) {
154
  $this->sync_product_bundle_meta( $original_bundle_id, $translation->element_id );
155
  }
173
  ) );
174
  }
175
 
 
176
  // Add Bundles Box to WCML Translation GUI
177
  public function custom_box_html( $obj, $bundle_id, $data ){
178
 
315
 
316
  }
317
 
318
+ // Update Bundled products title and description after saving the translation
319
  public function bundle_update( $bundle_id, $translated_bundle_id, $data, $lang ){
320
  global $wpdb;
321
 
608
 
609
  return $wpdb->insert_id;
610
  }
611
+
612
+ /**
613
+ * @param array $custom_fields
614
+ *
615
+ * @return array
616
+ */
617
+ public function get_price_custom_fields( $custom_fields ) {
618
+
619
+ $custom_fields = array_merge( $custom_fields, array(
620
+ '_wc_pb_base_regular_price',
621
+ '_wc_pb_base_sale_price',
622
+ '_wc_pb_base_price',
623
+ '_wc_sw_max_price',
624
+ '_wc_sw_max_regular_price'
625
+ ) );
626
+
627
+ return $custom_fields;
628
+ }
629
  }
compatibility/class-wcml-table-rate-shipping.php CHANGED
@@ -57,7 +57,7 @@ class WCML_Table_Rate_Shipping {
57
  if( isset( $_POST[ 'shipping_label' ] ) &&
58
  isset( $_POST[ 'woocommerce_table_rate_title' ] ) ){
59
  do_action( 'wpml_register_single_string', 'woocommerce', sanitize_text_field( $_POST[ 'woocommerce_table_rate_title' ] ) . '_shipping_method_title', sanitize_text_field( $_POST[ 'woocommerce_table_rate_title' ] ) );
60
- if( version_compare( WC()->version, '2.7', '<' ) ){
61
  $shipping_labels = array_map( 'woocommerce_clean', $_POST[ 'shipping_label' ] );
62
  } else{
63
  $shipping_labels = array_map( 'wc_clean', $_POST[ 'shipping_label' ] );
57
  if( isset( $_POST[ 'shipping_label' ] ) &&
58
  isset( $_POST[ 'woocommerce_table_rate_title' ] ) ){
59
  do_action( 'wpml_register_single_string', 'woocommerce', sanitize_text_field( $_POST[ 'woocommerce_table_rate_title' ] ) . '_shipping_method_title', sanitize_text_field( $_POST[ 'woocommerce_table_rate_title' ] ) );
60
+ if( version_compare( WC()->version, '3.0.0', '<' ) ){
61
  $shipping_labels = array_map( 'woocommerce_clean', $_POST[ 'shipping_label' ] );
62
  } else{
63
  $shipping_labels = array_map( 'wc_clean', $_POST[ 'shipping_label' ] );
compatibility/class-wcml-the-events-calendar.php CHANGED
@@ -87,8 +87,8 @@ class WCML_The_Events_Calendar{
87
 
88
  if( $post_id == $this->sitepress->get_original_element_id( $post_id, 'post_tribe_events' ) ){
89
 
90
- $tickets = [];
91
- $ticket_meta = [];
92
 
93
  if( class_exists('Tribe__Tickets__RSVP') ){
94
  $ticket_ids = Tribe__Tickets__RSVP::get_instance()->get_tickets_ids( $post_id );
@@ -120,7 +120,7 @@ class WCML_The_Events_Calendar{
120
 
121
  public function append_RSVP_tickets_to_translation_job( $package, $post ){
122
 
123
- if( $post->post_type == 'tribe_events' ){
124
 
125
  $ticket_lang = $this->sitepress->get_language_for_element( $post->ID, 'post_tribe_events' );
126
  $this->sitepress->switch_lang( $ticket_lang );
@@ -219,7 +219,7 @@ class WCML_The_Events_Calendar{
219
 
220
  public function append_woo_tickets_to_translation_job( $package, $post ){
221
 
222
- if( $post->post_type == 'tribe_events' ){
223
 
224
  $ticket_lang = $this->sitepress->get_language_for_element( $post->ID, 'post_tribe_events' );
225
  $this->sitepress->switch_lang( $ticket_lang );
87
 
88
  if( $post_id == $this->sitepress->get_original_element_id( $post_id, 'post_tribe_events' ) ){
89
 
90
+ $tickets = array();
91
+ $ticket_meta = array();
92
 
93
  if( class_exists('Tribe__Tickets__RSVP') ){
94
  $ticket_ids = Tribe__Tickets__RSVP::get_instance()->get_tickets_ids( $post_id );
120
 
121
  public function append_RSVP_tickets_to_translation_job( $package, $post ){
122
 
123
+ if( $post->post_type == 'tribe_events' && class_exists('Tribe__Tickets__RSVP') ){
124
 
125
  $ticket_lang = $this->sitepress->get_language_for_element( $post->ID, 'post_tribe_events' );
126
  $this->sitepress->switch_lang( $ticket_lang );
219
 
220
  public function append_woo_tickets_to_translation_job( $package, $post ){
221
 
222
+ if( $post->post_type == 'tribe_events' && class_exists('Tribe__Tickets_Plus__Commerce__WooCommerce__Main') ){
223
 
224
  $ticket_lang = $this->sitepress->get_language_for_element( $post->ID, 'post_tribe_events' );
225
  $this->sitepress->switch_lang( $ticket_lang );
compatibility/class-wcml-wc-memberships.php ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WCML_WC_Memberships{
4
+
5
+ public function add_hooks(){
6
+
7
+ add_filter( 'parse_request', array( $this, 'adjust_query_vars' ) );
8
+ add_filter( 'wcml_register_endpoints_query_vars', array( $this, 'register_endpoints_query_vars' ), 10, 3 );
9
+ add_filter( 'wcml_endpoint_permalink_filter', array( $this, 'endpoint_permalink_filter' ), 10, 2 );
10
+ add_filter( 'wc_memberships_members_area_my-memberships_actions', array( $this, 'filter_actions_links' ) );
11
+
12
+ add_action( 'wp_enqueue_scripts', array( $this, 'load_assets' ) );
13
+ }
14
+
15
+ public function register_endpoints_query_vars( $query_vars, $wc_vars, $object ){
16
+ $query_vars[ 'members_area' ] = $this->get_translated_endpoint( $object );
17
+
18
+ return $query_vars;
19
+ }
20
+
21
+ public function get_translated_endpoint( $object ){
22
+
23
+ $translation = $object->get_endpoint_translation(
24
+ 'members_area',
25
+ get_option( 'woocommerce_myaccount_members_area_endpoint', 'members-area' )
26
+ );
27
+
28
+ return $translation;
29
+ }
30
+
31
+ public function adjust_query_vars( $q ){
32
+
33
+ if( !isset( $q->query_vars['members-area'] ) && isset( $q->query_vars[ 'members_area' ] ) ){
34
+ $q->query_vars['members-area'] = $q->query_vars[ 'members_area' ];
35
+ }
36
+
37
+ return $q;
38
+ }
39
+
40
+ public function endpoint_permalink_filter( $endpoint, $key ){
41
+
42
+ if( 'members_area' === $key ){
43
+ $endpoint = get_option( 'woocommerce_myaccount_members_area_endpoint', 'members-area' );
44
+ }
45
+
46
+ return $endpoint;
47
+ }
48
+
49
+ public function filter_actions_links( $actions ){
50
+
51
+ foreach ( $actions as $key => $action ){
52
+ if( 'view' === $key ){
53
+ $membership_endpoints = $this->get_membership_endpoints();
54
+ $actions[ $key ][ 'url' ] = str_replace( $membership_endpoints[ 'original' ], $membership_endpoints[ 'translated' ], $action[ 'url' ] );
55
+ }
56
+ }
57
+
58
+ return $actions;
59
+ }
60
+
61
+ public function load_assets( ) {
62
+ global $post;
63
+
64
+ if( isset( $post->ID ) && wc_get_page_id( 'myaccount' ) == $post->ID ){
65
+ wp_register_script( 'wcml-members-js', WCML_PLUGIN_URL . '/compatibility/res/js/wcml-members.js', array( 'jquery' ), WCML_VERSION );
66
+ wp_enqueue_script( 'wcml-members-js' );
67
+ wp_localize_script( 'wcml-members-js', 'endpoints', $this->get_membership_endpoints() );
68
+ }
69
+
70
+ }
71
+
72
+ public function get_membership_endpoints(){
73
+
74
+ $endpoint = get_option( 'woocommerce_myaccount_members_area_endpoint', 'members-area' );
75
+ $translated_endpoint = apply_filters( 'wpml_translate_single_string', $endpoint, 'WooCommerce Endpoints', 'members_area' );
76
+
77
+ return array(
78
+ 'original' => $endpoint,
79
+ 'translated' => $translated_endpoint
80
+ );
81
+ }
82
+
83
+
84
+ }
compatibility/class-wcml-wc-subscriptions.php CHANGED
@@ -2,137 +2,140 @@
2
 
3
  class WCML_WC_Subscriptions{
4
 
5
- private $new_subscription = false;
6
-
7
- function __construct(){
8
-
9
- add_action('init', array($this, 'init'),9);
10
- add_filter('wcml_variation_term_taxonomy_ids',array($this,'wcml_variation_term_taxonomy_ids'));
11
- add_filter('woocommerce_subscription_lengths', array($this, 'woocommerce_subscription_lengths'), 10, 2);
12
-
13
- add_filter('wcml_register_endpoints_query_vars', array($this, 'register_endpoint' ), 10, 3 );
14
- add_filter('wcml_endpoint_permalink_filter', array($this, 'endpoint_permalink_filter'), 10, 2);
15
-
16
- //custom prices
17
- add_filter( 'wcml_custom_prices_fields', array( $this, 'set_prices_fields' ), 10, 2 );
18
- add_filter( 'wcml_custom_prices_strings', array( $this, 'set_labels_for_prices_fields' ), 10, 2 );
19
- add_filter( 'wcml_custom_prices_fields_labels', array( $this, 'set_labels_for_prices_fields' ), 10, 2 );
20
- add_filter( 'wcml_update_custom_prices_values', array( $this, 'update_custom_prices_values' ), 10 ,3 );
21
- add_action( 'wcml_after_custom_prices_block', array( $this, 'new_subscription_prices_block') );
22
-
23
- // reenable coupons for subscriptions when multicurrency is on
24
- add_action('woocommerce_subscription_cart_after_grouping', array($this, 'woocommerce_subscription_cart_after_grouping'));
25
-
26
- add_action( 'woocommerce_subscriptions_product_options_pricing', array( $this, 'show_pointer_info' ) );
27
- add_action( 'woocommerce_variable_subscription_pricing', array( $this, 'show_pointer_info' ) );
28
- }
29
-
30
- function init(){
31
- if( !is_admin() ){
32
- add_filter('woocommerce_subscriptions_product_sign_up_fee', array($this, 'product_price_filter'), 10, 2);
33
- }
34
- }
35
-
36
- function product_price_filter($subscription_sign_up_fee, $product){
37
-
38
- $subscription_sign_up_fee = apply_filters('wcml_raw_price_amount', $subscription_sign_up_fee );
39
-
40
- return $subscription_sign_up_fee;
41
- }
42
-
43
- function wcml_variation_term_taxonomy_ids($get_variation_term_taxonomy_ids){
44
- global $wpdb;
45
- $get_variation_term_taxonomy_id = $wpdb->get_var("SELECT tt.term_taxonomy_id FROM $wpdb->terms AS t LEFT JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id WHERE t.slug = 'variable-subscription'");
46
-
47
- if(!empty($get_variation_term_taxonomy_id)){
48
- $get_variation_term_taxonomy_ids[] = $get_variation_term_taxonomy_id;
49
- }
50
-
51
- return $get_variation_term_taxonomy_ids;
52
- }
53
-
54
- public function woocommerce_subscription_lengths($subscription_ranges, $subscription_period) {
55
-
56
- if (is_array($subscription_ranges)) {
57
- foreach ($subscription_ranges as $period => $ranges) {
58
- if (is_array($ranges)) {
59
- foreach ($ranges as $range) {
60
- if ($range == "9 months") {
61
- $breakpoint = true;
62
- }
63
- $new_subscription_ranges[$period][] = apply_filters( 'wpml_translate_single_string', $range, 'wc_subscription_ranges', $range);
64
- }
65
- }
66
- }
67
- }
68
-
69
- return isset($new_subscription_ranges) ? $new_subscription_ranges : $subscription_ranges;
70
- }
71
-
72
- public function woocommerce_subscription_cart_after_grouping() {
73
- global $woocommerce_wpml;
74
-
75
- if( $woocommerce_wpml->settings['enable_multi_currency'] == WCML_MULTI_CURRENCIES_INDEPENDENT ){
76
- remove_action('woocommerce_before_calculate_totals', 'WC_Subscriptions_Coupon::remove_coupons', 10);
77
- }
78
-
79
- }
80
-
81
- function set_prices_fields( $fields, $product_id ){
82
- if( $this->is_subscriptions_product( $product_id ) || $this->new_subscription ){
83
- $fields[] = '_subscription_sign_up_fee';
84
- }
85
-
86
- return $fields;
87
-
88
- }
89
-
90
- function set_labels_for_prices_fields( $labels, $product_id ){
91
-
92
- if( $this->is_subscriptions_product( $product_id ) || $this->new_subscription ){
93
- $labels[ '_regular_price' ] = __( 'Subscription Price', 'woocommerce-multilingual' );
94
- $labels[ '_subscription_sign_up_fee' ] = __( 'Sign-up Fee', 'woocommerce-multilingual' );
95
- }
96
-
97
- return $labels;
98
-
99
- }
100
-
101
- function update_custom_prices_values( $prices, $code, $variation_id = false ){
102
-
103
- if( isset( $_POST[ '_custom_subscription_sign_up_fee' ][ $code ] ) ){
104
- $prices[ '_subscription_sign_up_fee' ] = wc_format_decimal( $_POST[ '_custom_subscription_sign_up_fee' ][ $code ] );
105
- }
106
-
107
- if( $variation_id && isset( $_POST[ '_custom_variation_subscription_sign_up_fee' ][ $code ][ $variation_id ] ) ){
108
- $prices[ '_subscription_sign_up_fee' ] = wc_format_decimal( $_POST[ '_custom__custom_variation_subscription_sign_up_fee' ][ $code ][ $variation_id ] );
109
- }
110
-
111
- return $prices;
112
-
113
- }
114
-
115
- function is_subscriptions_product( $product_id ){
116
- global $wpdb;
117
- $get_variation_term_taxonomy_ids = $wpdb->get_col("SELECT tt.term_taxonomy_id FROM $wpdb->terms AS t LEFT JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id WHERE t.slug IN ( 'subscription', 'variable-subscription' ) AND tt.taxonomy = 'product_type'");
118
-
119
- if( get_post_type( $product_id ) == 'product_variation' ){
120
- $product_id = wp_get_post_parent_id( $product_id );
121
- }
122
-
123
- $is_subscriptions_product = $wpdb->get_var($wpdb->prepare("SELECT count(object_id) FROM $wpdb->term_relationships WHERE object_id = %d AND term_taxonomy_id IN (".join(',',$get_variation_term_taxonomy_ids).")",$product_id));
124
- return $is_subscriptions_product;
125
- }
126
-
127
- function new_subscription_prices_block( $product_id ){
128
- global $woocommerce_wpml;
129
- if( $product_id == 'new' ){
130
- $this->new_subscription = true;
131
- echo '<div class="wcml_prices_if_subscription" style="display: none">';
132
- $custom_prices_ui = new WCML_Custom_Prices_UI( $woocommerce_wpml, 'new' );
133
- $custom_prices_ui->show();
134
- echo '</div>';
135
- ?>
 
 
 
136
  <script>
137
  jQuery(document).ready(function($) {
138
  jQuery('.wcml_prices_if_subscription .wcml_custom_prices_input').attr('name', '_wcml_custom_prices[new_subscription]').attr( 'id', '_wcml_custom_prices[new_subscription]');
@@ -167,34 +170,54 @@ class WCML_WC_Subscriptions{
167
  });
168
  });
169
  </script>
170
- <?php
171
- }
172
- }
173
-
174
- function register_endpoint( $query_vars, $wc_vars, $obj ){
175
-
176
- $query_vars[ 'view-subscription' ] = $obj->get_endpoint_translation( 'view-subscription', isset( $wc_vars['view-subscription'] ) ? $wc_vars['view-subscription'] : 'view-subscription' );
177
- return $query_vars;
178
- }
179
-
180
- function endpoint_permalink_filter( $endpoint, $key ){
181
-
182
- if( $key == 'view-subscription' ){
183
- return 'view-subscription';
184
- }
185
-
186
- return $endpoint;
187
- }
188
-
189
- public function show_pointer_info(){
190
-
191
- $pointer_ui = new WCML_Pointer_UI(
192
- sprintf( __( 'You can translate strings related to subscription products on the %sWPML String Translation page%s. Use the search on the top of that page to find the strings.', 'woocommerce-multilingual' ), '<a href="'.admin_url('admin.php?page='.WPML_ST_FOLDER.'/menu/string-translation.php&context=woocommerce_subscriptions').'">', '</a>' ),
193
- 'https://wpml.org/documentation/woocommerce-extensions-compatibility/translating-woocommerce-subscriptions-woocommerce-multilingual/',
194
- 'general_product_data .subscription_pricing',
195
- 'prepend'
196
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
197
 
198
- $pointer_ui->show();
199
- }
200
  }
2
 
3
  class WCML_WC_Subscriptions{
4
 
5
+ private $new_subscription = false;
6
+
7
+ function __construct(){
8
+
9
+ add_action('init', array($this, 'init'),9);
10
+ add_filter('wcml_variation_term_taxonomy_ids',array($this,'wcml_variation_term_taxonomy_ids'));
11
+ add_filter('woocommerce_subscription_lengths', array($this, 'woocommerce_subscription_lengths'), 10, 2);
12
+
13
+ add_filter('wcml_register_endpoints_query_vars', array($this, 'register_endpoint' ), 10, 3 );
14
+ add_filter('wcml_endpoint_permalink_filter', array($this, 'endpoint_permalink_filter'), 10, 2);
15
+
16
+ //custom prices
17
+ add_filter( 'wcml_custom_prices_fields', array( $this, 'set_prices_fields' ), 10, 2 );
18
+ add_filter( 'wcml_custom_prices_strings', array( $this, 'set_labels_for_prices_fields' ), 10, 2 );
19
+ add_filter( 'wcml_custom_prices_fields_labels', array( $this, 'set_labels_for_prices_fields' ), 10, 2 );
20
+ add_filter( 'wcml_update_custom_prices_values', array( $this, 'update_custom_prices_values' ), 10 ,3 );
21
+ add_action( 'wcml_after_custom_prices_block', array( $this, 'new_subscription_prices_block') );
22
+
23
+ // reenable coupons for subscriptions when multicurrency is on
24
+ add_action('woocommerce_subscription_cart_after_grouping', array($this, 'woocommerce_subscription_cart_after_grouping'));
25
+
26
+ add_action( 'woocommerce_subscriptions_product_options_pricing', array( $this, 'show_pointer_info' ) );
27
+ add_action( 'woocommerce_variable_subscription_pricing', array( $this, 'show_pointer_info' ) );
28
+ }
29
+
30
+ function init(){
31
+ if( !is_admin() ){
32
+ add_filter('woocommerce_subscriptions_product_sign_up_fee', array($this, 'product_price_filter'), 10, 2);
33
+
34
+ add_action( 'woocommerce_before_calculate_totals', array( $this, 'maybe_backup_recurring_carts'), 1 );
35
+ add_action( 'woocommerce_after_calculate_totals', array( $this, 'maybe_restore_recurring_carts'), 200 );
36
+ }
37
+ }
38
+
39
+ function product_price_filter($subscription_sign_up_fee, $product){
40
+
41
+ $subscription_sign_up_fee = apply_filters('wcml_raw_price_amount', $subscription_sign_up_fee );
42
+
43
+ return $subscription_sign_up_fee;
44
+ }
45
+
46
+ function wcml_variation_term_taxonomy_ids($get_variation_term_taxonomy_ids){
47
+ global $wpdb;
48
+ $get_variation_term_taxonomy_id = $wpdb->get_var("SELECT tt.term_taxonomy_id FROM $wpdb->terms AS t LEFT JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id WHERE t.slug = 'variable-subscription'");
49
+
50
+ if(!empty($get_variation_term_taxonomy_id)){
51
+ $get_variation_term_taxonomy_ids[] = $get_variation_term_taxonomy_id;
52
+ }
53
+
54
+ return $get_variation_term_taxonomy_ids;
55
+ }
56
+
57
+ public function woocommerce_subscription_lengths($subscription_ranges, $subscription_period) {
58
+
59
+ if (is_array($subscription_ranges)) {
60
+ foreach ($subscription_ranges as $period => $ranges) {
61
+ if (is_array($ranges)) {
62
+ foreach ($ranges as $range) {
63
+ if ($range == "9 months") {
64
+ $breakpoint = true;
65
+ }
66
+ $new_subscription_ranges[$period][] = apply_filters( 'wpml_translate_single_string', $range, 'wc_subscription_ranges', $range);
67
+ }
68
+ }
69
+ }
70
+ }
71
+
72
+ return isset($new_subscription_ranges) ? $new_subscription_ranges : $subscription_ranges;
73
+ }
74
+
75
+ public function woocommerce_subscription_cart_after_grouping() {
76
+ global $woocommerce_wpml;
77
+
78
+ if( $woocommerce_wpml->settings['enable_multi_currency'] == WCML_MULTI_CURRENCIES_INDEPENDENT ){
79
+ remove_action('woocommerce_before_calculate_totals', 'WC_Subscriptions_Coupon::remove_coupons', 10);
80
+ }
81
+
82
+ }
83
+
84
+ function set_prices_fields( $fields, $product_id ){
85
+ if( $this->is_subscriptions_product( $product_id ) || $this->new_subscription ){
86
+ $fields[] = '_subscription_sign_up_fee';
87
+ }
88
+
89
+ return $fields;
90
+
91
+ }
92
+
93
+ function set_labels_for_prices_fields( $labels, $product_id ){
94
+
95
+ if( $this->is_subscriptions_product( $product_id ) || $this->new_subscription ){
96
+ $labels[ '_regular_price' ] = __( 'Subscription Price', 'woocommerce-multilingual' );
97
+ $labels[ '_subscription_sign_up_fee' ] = __( 'Sign-up Fee', 'woocommerce-multilingual' );
98
+ }
99
+
100
+ return $labels;
101
+
102
+ }
103
+
104
+ function update_custom_prices_values( $prices, $code, $variation_id = false ){
105
+
106
+ if( isset( $_POST[ '_custom_subscription_sign_up_fee' ][ $code ] ) ){
107
+ $prices[ '_subscription_sign_up_fee' ] = wc_format_decimal( $_POST[ '_custom_subscription_sign_up_fee' ][ $code ] );
108
+ }
109
+
110
+ if( $variation_id && isset( $_POST[ '_custom_variation_subscription_sign_up_fee' ][ $code ][ $variation_id ] ) ){
111
+ $prices[ '_subscription_sign_up_fee' ] = wc_format_decimal( $_POST[ '_custom__custom_variation_subscription_sign_up_fee' ][ $code ][ $variation_id ] );
112
+ }
113
+
114
+ return $prices;
115
+
116
+ }
117
+
118
+ function is_subscriptions_product( $product_id ){
119
+ global $wpdb;
120
+ $get_variation_term_taxonomy_ids = $wpdb->get_col("SELECT tt.term_taxonomy_id FROM $wpdb->terms AS t LEFT JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id WHERE t.slug IN ( 'subscription', 'variable-subscription' ) AND tt.taxonomy = 'product_type'");
121
+
122
+ if( get_post_type( $product_id ) == 'product_variation' ){
123
+ $product_id = wp_get_post_parent_id( $product_id );
124
+ }
125
+
126
+ $is_subscriptions_product = $wpdb->get_var($wpdb->prepare("SELECT count(object_id) FROM $wpdb->term_relationships WHERE object_id = %d AND term_taxonomy_id IN (".join(',',$get_variation_term_taxonomy_ids).")",$product_id));
127
+ return $is_subscriptions_product;
128
+ }
129
+
130
+ function new_subscription_prices_block( $product_id ){
131
+ global $woocommerce_wpml;
132
+ if( $product_id == 'new' ){
133
+ $this->new_subscription = true;
134
+ echo '<div class="wcml_prices_if_subscription" style="display: none">';
135
+ $custom_prices_ui = new WCML_Custom_Prices_UI( $woocommerce_wpml, 'new' );
136
+ $custom_prices_ui->show();
137
+ echo '</div>';
138
+ ?>
139
  <script>
140
  jQuery(document).ready(function($) {
141
  jQuery('.wcml_prices_if_subscription .wcml_custom_prices_input').attr('name', '_wcml_custom_prices[new_subscription]').attr( 'id', '_wcml_custom_prices[new_subscription]');
170
  });
171
  });
172
  </script>
173
+ <?php
174
+ }
175
+ }
176
+
177
+ function register_endpoint( $query_vars, $wc_vars, $obj ){
178
+
179
+ $query_vars[ 'view-subscription' ] = $obj->get_endpoint_translation( 'view-subscription', isset( $wc_vars['view-subscription'] ) ? $wc_vars['view-subscription'] : 'view-subscription' );
180
+ return $query_vars;
181
+ }
182
+
183
+ function endpoint_permalink_filter( $endpoint, $key ){
184
+
185
+ if( $key == 'view-subscription' ){
186
+ return 'view-subscription';
187
+ }
188
+
189
+ return $endpoint;
190
+ }
191
+
192
+ public function show_pointer_info(){
193
+
194
+ $pointer_ui = new WCML_Pointer_UI(
195
+ sprintf( __( 'You can translate strings related to subscription products on the %sWPML String Translation page%s. Use the search on the top of that page to find the strings.', 'woocommerce-multilingual' ), '<a href="'.admin_url('admin.php?page='.WPML_ST_FOLDER.'/menu/string-translation.php&context=woocommerce_subscriptions').'">', '</a>' ),
196
+ 'https://wpml.org/documentation/woocommerce-extensions-compatibility/translating-woocommerce-subscriptions-woocommerce-multilingual/',
197
+ 'general_product_data .subscription_pricing',
198
+ 'prepend'
199
+ );
200
+
201
+ $pointer_ui->show();
202
+ }
203
+
204
+ /**
205
+ * @param WC_Cart $cart
206
+ */
207
+ public function maybe_backup_recurring_carts( $cart ){
208
+ if( ! empty( $cart->recurring_carts ) ){
209
+ $this->recurring_carts = $cart->recurring_carts;
210
+ }
211
+ }
212
+
213
+ /**
214
+ * @param WC_Cart $cart
215
+ */
216
+ public function maybe_restore_recurring_carts( $cart ){
217
+ if( ! empty( $this->recurring_carts ) ){
218
+ $cart->recurring_carts = $this->recurring_carts;
219
+ $this->recurring_carts = null;
220
+ }
221
+ }
222
 
 
 
223
  }
compatibility/class-wcml-wcexporter.php CHANGED
@@ -42,7 +42,7 @@ class WCML_wcExporter{
42
  global $sitepress,$woocommerce_wpml;
43
 
44
  $data->language = $sitepress->get_language_for_element($product_id,'post_'.get_post_type($product_id));
45
- $data->translation_of = apply_filters( 'translate_object_id',$product_id,get_post_type($product_id),true, $woocommerce_wpml->products->get_original_product_language( $product_id ) );
46
 
47
  return $data;
48
  }
42
  global $sitepress,$woocommerce_wpml;
43
 
44
  $data->language = $sitepress->get_language_for_element($product_id,'post_'.get_post_type($product_id));
45
+ $data->translation_of = $this->woocommerce_wpml->products->get_original_product_id( $product_id );
46
 
47
  return $data;
48
  }
compatibility/class-wcml-yith-wcqv.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WCML_YITH_WCQV{
4
+
5
+ public function add_hooks(){
6
+
7
+ add_filter( 'wcml_multi_currency_ajax_actions', array( $this, 'ajax_action_needs_multi_currency' ) );
8
+
9
+ }
10
+
11
+ function ajax_action_needs_multi_currency( $actions ){
12
+
13
+ $actions[] = 'yith_load_product_quick_view';
14
+
15
+ return $actions;
16
+ }
17
+
18
+ }
compatibility/includes/class-wcml-wc-product-bundles-items.php CHANGED
@@ -24,7 +24,12 @@ class WCML_WC_Product_Bundles_Items{
24
  * @return array
25
  */
26
  function get_item_data( $bundled_item ){
27
- return $bundled_item->get_data();
 
 
 
 
 
28
  }
29
 
30
  function copy_item_data( $item_id_1, $item_id_2 ){
24
  * @return array
25
  */
26
  function get_item_data( $bundled_item ){
27
+ $item_data = $bundled_item->get_data();
28
+ // #wcml-1927 - Insufficient Stock issue
29
+ if ( $item_data['max_stock'] === null ) {
30
+ $item_data['max_stock'] = '';
31
+ }
32
+ return $item_data;
33
  }
34
 
35
  function copy_item_data( $item_id_1, $item_id_2 ){
compatibility/res/js/wcml-members.js ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery( document ).ready( function( $ ){
2
+
3
+ if( typeof endpoints != 'undefined' ){
4
+
5
+ var tabs = [ 'my-membership-content', 'my-membership-products', 'my-membership-discounts', 'my-membership-notes'];
6
+
7
+ for ( i = 0; i < tabs.length; i++ ) {
8
+ var link = $('.'+tabs[i]+' a'),
9
+ link_href = link.attr('href');
10
+ if ( link_href ){
11
+ link.attr('href', link_href.replace( endpoints.original, endpoints.translated ));
12
+ }
13
+ }
14
+ }
15
+
16
+ });
17
+
18
+
19
+
inc/abstracts/class-wcml-exchange-rate-service.php CHANGED
@@ -78,7 +78,7 @@ abstract class WCML_Exchange_Rate_Service{
78
  * @return bool
79
  */
80
  public function is_key_required(){
81
- return static::REQUIRES_KEY;
82
  }
83
 
84
  /**
78
  * @return bool
79
  */
80
  public function is_key_required(){
81
+ return self::REQUIRES_KEY;
82
  }
83
 
84
  /**
inc/admin-menus/class-wcml-admin-menus.php CHANGED
@@ -216,7 +216,8 @@ class WCML_Admin_Menus{
216
  !isset( $_GET[ 'action' ] ) ||
217
  ( isset( $_GET[ 'action' ] ) && !in_array( $_GET[ 'action' ], array( 'trash', 'delete' ) ) )
218
  ) {
219
- wp_redirect( admin_url( 'admin.php?page=wpml-wcml&tab=products' ) );
 
220
  exit;
221
  }
222
  }
@@ -267,7 +268,7 @@ class WCML_Admin_Menus{
267
  global $submenu, $menu;
268
 
269
  if (
270
- class_exists( 'woocommerce' ) &&
271
  (
272
  empty( self::$woocommerce_wpml->settings['set_up_wizard_run'] ) ||
273
  (
216
  !isset( $_GET[ 'action' ] ) ||
217
  ( isset( $_GET[ 'action' ] ) && !in_array( $_GET[ 'action' ], array( 'trash', 'delete' ) ) )
218
  ) {
219
+ $prid = (int)$_GET[ 'post' ];
220
+ wp_redirect( admin_url( 'admin.php?page=wpml-wcml&tab=products&prid='.$prid ) );
221
  exit;
222
  }
223
  }
268
  global $submenu, $menu;
269
 
270
  if (
271
+ class_exists( 'WooCommerce' ) &&
272
  (
273
  empty( self::$woocommerce_wpml->settings['set_up_wizard_run'] ) ||
274
  (
inc/admin-menus/class-wcml-taxonomy-translation-link-filters.php ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WCML_Taxonomy_Translation_Link_Filters{
4
+
5
+ /**
6
+ * @var WCML_Attributes
7
+ */
8
+ private $wcml_attributes;
9
+
10
+ public function __construct( $wcml_attributes ) {
11
+ $this->wcml_attributes = $wcml_attributes;
12
+ }
13
+
14
+ public function add_filters(){
15
+ add_filter( 'wpml_notice_text_taxonomy-term-help-notices', array( $this, 'override_translation_notice_text' ), 10, 2 );
16
+
17
+ }
18
+
19
+ /**
20
+ * @param string text
21
+ * @param WPML_Notice $notice
22
+ *
23
+ * @return string
24
+ */
25
+ public function override_translation_notice_text( $text, $notice ) {
26
+
27
+ $taxonomy = get_taxonomy( $notice->get_id() );
28
+ if ( false !== $taxonomy ) {
29
+
30
+ $link = sprintf(
31
+ '<a href="%s">%s</a>',
32
+ $this->get_screen_url( $taxonomy->name ),
33
+ sprintf ( __( '%s translation', 'woocommerce-multilingual' ), $taxonomy->labels->singular_name )
34
+ );
35
+
36
+ $text = sprintf(
37
+ esc_html__( 'Translating %s? Use the %s table for easier translation.', 'woocommerce-multilingual' ),
38
+ $taxonomy->labels->name,
39
+ $link
40
+ );
41
+ }
42
+
43
+ return $text;
44
+ }
45
+
46
+ /**
47
+ * @param string $taxonomy
48
+ *
49
+ * @return string
50
+ */
51
+ public function get_screen_url( $taxonomy = '' ){
52
+
53
+ $url = false;
54
+
55
+ $built_in_taxonomies = array( 'product_cat', 'product_tag', 'product_shipping_class' );
56
+ if( in_array( $taxonomy, $built_in_taxonomies ) ){
57
+
58
+ $url = add_query_arg( array( 'tab' => $taxonomy ), admin_url( 'admin.php?page=wpml-wcml' ) ) ;
59
+
60
+ } else {
61
+
62
+ $attributes = $this->wcml_attributes->get_translatable_attributes();
63
+ $translatable_attributes = array();
64
+ foreach( $attributes as $attribute ){
65
+ $translatable_attributes[] = 'pa_' . $attribute->attribute_name;
66
+ }
67
+
68
+ if( in_array( $taxonomy, $translatable_attributes ) ) {
69
+
70
+ $url = add_query_arg(
71
+ array( 'taxonomy' => $taxonomy ),
72
+ admin_url( 'admin.php?page=wpml-wcml&tab=product-attributes' )
73
+ );
74
+
75
+ }else{
76
+
77
+ $custom_taxonomies = get_object_taxonomies( 'product', 'objects' );
78
+
79
+ $translatable_taxonomies = array();
80
+ foreach( $custom_taxonomies as $product_taxonomy_name => $product_taxonomy_object ){
81
+ if( is_taxonomy_translated( $product_taxonomy_name ) ){
82
+ $translatable_taxonomies[] = $product_taxonomy_name;
83
+ }
84
+ }
85
+
86
+ if ( in_array( $taxonomy, $translatable_taxonomies ) ) {
87
+
88
+ $url = add_query_arg(
89
+ array( 'taxonomy' => $taxonomy ),
90
+ admin_url( 'admin.php?page=wpml-wcml&tab=custom-taxonomies' )
91
+ );
92
+
93
+ }
94
+
95
+ }
96
+
97
+ }
98
+
99
+ return $url;
100
+ }
101
+
102
+ }
inc/class-wcml-attributes.php CHANGED
@@ -23,7 +23,7 @@ class WCML_Attributes{
23
 
24
  add_action( 'woocommerce_before_attribute_delete', array( $this, 'refresh_taxonomy_translations_cache' ), 10, 3 );
25
 
26
- if( ( defined('WC_VERSION') && version_compare( WC_VERSION , '2.7', '<' ) ) ){
27
  add_filter( 'woocommerce_get_product_attributes', array( $this, 'filter_adding_to_cart_product_attributes_names' ) );
28
  }else{
29
  add_filter( 'woocommerce_product_get_attributes', array( $this, 'filter_adding_to_cart_product_attributes_names' ) );
23
 
24
  add_action( 'woocommerce_before_attribute_delete', array( $this, 'refresh_taxonomy_translations_cache' ), 10, 3 );
25
 
26
+ if( ( defined('WC_VERSION') && version_compare( WC_VERSION , '3.0.0', '<' ) ) ){
27
  add_filter( 'woocommerce_get_product_attributes', array( $this, 'filter_adding_to_cart_product_attributes_names' ) );
28
  }else{
29
  add_filter( 'woocommerce_product_get_attributes', array( $this, 'filter_adding_to_cart_product_attributes_names' ) );
inc/class-wcml-cart.php CHANGED
@@ -191,7 +191,7 @@ class WCML_Cart
191
  $tr_product_id = apply_filters( 'translate_object_id', $cart_item[ 'product_id' ], 'product', false, $current_language );
192
  //translate custom attr labels in cart object
193
 
194
- if( version_compare( WC_VERSION , '2.7', '<' ) && isset( $cart_item[ 'data' ]->product_attributes ) ){
195
  foreach( $cart_item[ 'data' ]->product_attributes as $attr_key => $product_attribute ){
196
  if( isset( $product_attribute[ 'is_taxonomy' ]) && !$product_attribute[ 'is_taxonomy' ] ){
197
  $cart->cart_contents[ $key ][ 'data' ]->product_attributes[ $attr_key ][ 'name' ] = $this->woocommerce_wpml->strings->translated_attribute_label(
@@ -230,13 +230,21 @@ class WCML_Cart
230
  if( !is_null( $tr_variation_id ) ){
231
  $cart->cart_contents[ $key ][ 'product_id' ] = intval( $tr_product_id );
232
  $cart->cart_contents[ $key ][ 'variation_id' ] = intval( $tr_variation_id );
233
- $cart->cart_contents[ $key ][ 'data' ]->id = intval( $tr_product_id );
 
 
 
 
234
  $cart->cart_contents[ $key ][ 'data' ]->post = get_post( $tr_product_id );
235
  }
236
  }else{
237
  if( !is_null( $tr_product_id ) ){
238
  $cart->cart_contents[ $key ][ 'product_id' ] = intval( $tr_product_id );
239
- $cart->cart_contents[ $key ][ 'data' ]->id = intval( $tr_product_id );
 
 
 
 
240
  $cart->cart_contents[ $key ][ 'data' ]->post = get_post( $tr_product_id );
241
  }
242
  }
@@ -348,8 +356,8 @@ class WCML_Cart
348
  $item[ 'variation_id' ] = apply_filters( 'translate_object_id',$item[ 'variation_id' ], 'product_variation', true );
349
  }
350
 
351
- if( version_compare( WC()->version, '2.7', '>=' ) ){
352
- $item[ 'data' ]->set_name( get_the_title( $item[ 'product_id' ] ) );
353
  } else {
354
  $item[ 'data' ]->post->post_title = get_the_title( $item[ 'product_id' ] );
355
  }
191
  $tr_product_id = apply_filters( 'translate_object_id', $cart_item[ 'product_id' ], 'product', false, $current_language );
192
  //translate custom attr labels in cart object
193
 
194
+ if( version_compare( WC_VERSION , '3.0.0', '<' ) && isset( $cart_item[ 'data' ]->product_attributes ) ){
195
  foreach( $cart_item[ 'data' ]->product_attributes as $attr_key => $product_attribute ){
196
  if( isset( $product_attribute[ 'is_taxonomy' ]) && !$product_attribute[ 'is_taxonomy' ] ){
197
  $cart->cart_contents[ $key ][ 'data' ]->product_attributes[ $attr_key ][ 'name' ] = $this->woocommerce_wpml->strings->translated_attribute_label(
230
  if( !is_null( $tr_variation_id ) ){
231
  $cart->cart_contents[ $key ][ 'product_id' ] = intval( $tr_product_id );
232
  $cart->cart_contents[ $key ][ 'variation_id' ] = intval( $tr_variation_id );
233
+ if( defined('WC_VERSION') && version_compare( WC_VERSION , '2.7', '<' ) ){
234
+ $cart->cart_contents[ $key ][ 'data' ]->id = intval( $tr_product_id );
235
+ }else{
236
+ $cart->cart_contents[ $key ][ 'data' ]->set_id( intval( $tr_product_id ) );
237
+ }
238
  $cart->cart_contents[ $key ][ 'data' ]->post = get_post( $tr_product_id );
239
  }
240
  }else{
241
  if( !is_null( $tr_product_id ) ){
242
  $cart->cart_contents[ $key ][ 'product_id' ] = intval( $tr_product_id );
243
+ if( defined('WC_VERSION') && version_compare( WC_VERSION , '2.7', '<' ) ){
244
+ $cart->cart_contents[ $key ][ 'data' ]->id = intval( $tr_product_id );
245
+ }else{
246
+ $cart->cart_contents[ $key ][ 'data' ]->set_id( intval( $tr_product_id ) );
247
+ }
248
  $cart->cart_contents[ $key ][ 'data' ]->post = get_post( $tr_product_id );
249
  }
250
  }
356
  $item[ 'variation_id' ] = apply_filters( 'translate_object_id',$item[ 'variation_id' ], 'product_variation', true );
357
  }
358
 
359
+ if( version_compare( WC()->version, '3.0.0', '>=' ) ){
360
+ $item[ 'data' ]->set_name( get_the_title( $item[ 'product_id' ] ) );
361
  } else {
362
  $item[ 'data' ]->post->post_title = get_the_title( $item[ 'product_id' ] );
363
  }
inc/class-wcml-compatibility.php CHANGED
@@ -180,6 +180,24 @@ class WCML_Compatibility {
180
  new WCML_The_Events_Calendar( $this->sitepress, $this->woocommerce_wpml );
181
  }
182
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
183
 
184
  }
185
 
180
  new WCML_The_Events_Calendar( $this->sitepress, $this->woocommerce_wpml );
181
  }
182
 
183
+ // Klarna Gateway
184
+ if( class_exists( 'WC_Gateway_Klarna' ) ){
185
+ $this->klarna_gateway = new WCML_Klarna_Gateway();
186
+ $this->klarna_gateway->add_hooks();
187
+ }
188
+
189
+ // YITH_WCQV
190
+ if( class_exists( 'YITH_WCQV' ) ){
191
+ $this->yith_wcqv = new WCML_YITH_WCQV();
192
+ $this->yith_wcqv->add_hooks();
193
+ }
194
+
195
+ // Woocommerce Memberships
196
+ if( class_exists( 'WC_Memberships' ) ){
197
+ $this->wc_memberships = new WCML_WC_Memberships();
198
+ $this->wc_memberships->add_hooks();
199
+ }
200
+
201
 
202
  }
203
 
inc/class-wcml-dependencies.php CHANGED
@@ -29,7 +29,7 @@ class WCML_Dependencies{
29
  $this->allok = false;
30
  }
31
 
32
- if(!class_exists('woocommerce')){
33
  $this->missing['WooCommerce'] = 'http://www.woothemes.com/woocommerce/';
34
  $this->allok = false;
35
  }elseif( ( defined('WC_VERSION') && version_compare( WC_VERSION , '2.1', '<' ) ) || ( isset( $woocommerce->version ) && version_compare( $woocommerce->version , '2.1', '<' ) ) ){
29
  $this->allok = false;
30
  }
31
 
32
+ if( !class_exists( 'WooCommerce' ) || !function_exists( 'WC' ) ){
33
  $this->missing['WooCommerce'] = 'http://www.woothemes.com/woocommerce/';
34
  $this->allok = false;
35
  }elseif( ( defined('WC_VERSION') && version_compare( WC_VERSION , '2.1', '<' ) ) || ( isset( $woocommerce->version ) && version_compare( $woocommerce->version , '2.1', '<' ) ) ){
inc/class-wcml-emails.php CHANGED
@@ -9,6 +9,7 @@ class WCML_Emails{
9
  function __construct( &$woocommerce_wpml, &$sitepress ) {
10
  $this->woocommerce_wpml = $woocommerce_wpml;
11
  $this->sitepress = $sitepress;
 
12
  add_action( 'init', array( $this, 'init' ) );
13
  }
14
 
@@ -23,8 +24,8 @@ class WCML_Emails{
23
  add_action('woocommerce_new_customer_note_notification', array($this, 'email_heading_note'),9);
24
  add_action('wp_ajax_woocommerce_mark_order_complete',array($this,'email_refresh_in_ajax'),9);
25
 
26
- add_action( 'woocommerce_order_status_pending_to_processing_notification', array( $this, 'email_heading_processing' ) );
27
- add_action( 'woocommerce_order_status_pending_to_on-hold_notification', array( $this, 'email_heading_processing' ) );
28
 
29
  //wrappers for email's body
30
  add_action('woocommerce_before_resend_order_emails', array($this, 'email_header'));
@@ -76,6 +77,8 @@ class WCML_Emails{
76
  ){
77
  add_filter( 'woocommerce_order_items_meta_get_formatted', array( $this, 'filter_formatted_items' ), 10, 2 );
78
  }
 
 
79
  }
80
 
81
  function email_refresh_in_ajax(){
@@ -160,16 +163,17 @@ class WCML_Emails{
160
 
161
  function email_heading_processing($order_id){
162
  global $woocommerce;
163
- if( class_exists( 'WC_Email_Customer_Processing_Order' ) && isset( $woocommerce->mailer()->emails[ 'WC_Email_Customer_Processing_Order' ] ) ){
164
 
165
- $woocommerce->mailer()->emails['WC_Email_Customer_Processing_Order']->heading = $this->wcml_get_translated_email_string( 'admin_texts_woocommerce_customer_processing_order_settings', '[woocommerce_customer_processing_order_settings]heading' );
166
 
167
- $woocommerce->mailer()->emails['WC_Email_Customer_Processing_Order']->subject = $this->wcml_get_translated_email_string( 'admin_texts_woocommerce_customer_processing_order_settings', '[woocommerce_customer_processing_order_settings]subject' );
168
 
 
169
  $enabled = $woocommerce->mailer()->emails['WC_Email_Customer_Processing_Order']->enabled;
170
  $woocommerce->mailer()->emails['WC_Email_Customer_Processing_Order']->enabled = false;
171
  $woocommerce->mailer()->emails['WC_Email_Customer_Processing_Order']->trigger($order_id);
172
  $woocommerce->mailer()->emails['WC_Email_Customer_Processing_Order']->enabled = $enabled;
 
173
  }
174
  }
175
 
@@ -195,10 +199,10 @@ class WCML_Emails{
195
 
196
  $woocommerce->mailer()->emails['WC_Email_Customer_Refunded_Order']->heading =
197
  $this->wcml_get_translated_email_string( 'admin_texts_woocommerce_customer_refunded_order_settings',
198
- '[woocommerce_customer_refunded_order_settings]heading_partial' );
199
  $woocommerce->mailer()->emails['WC_Email_Customer_Refunded_Order']->subject =
200
  $this->wcml_get_translated_email_string( 'admin_texts_woocommerce_customer_refunded_order_settings',
201
- '[woocommerce_customer_refunded_order_settings]subject_partial' );
202
 
203
  $enabled = $woocommerce->mailer()->emails['WC_Email_Customer_Refunded_Order']->enabled;
204
  $woocommerce->mailer()->emails['WC_Email_Customer_Refunded_Order']->enabled = false;
@@ -223,9 +227,9 @@ class WCML_Emails{
223
 
224
  $this->change_email_language( $user_lang );
225
 
226
- $woocommerce->mailer()->emails['WC_Email_New_Order']->heading = $this->wcml_get_translated_email_string( 'admin_texts_woocommerce_new_order_settings', '[woocommerce_new_order_settings]heading' );
227
 
228
- $woocommerce->mailer()->emails['WC_Email_New_Order']->subject = $this->wcml_get_translated_email_string( 'admin_texts_woocommerce_new_order_settings', '[woocommerce_new_order_settings]subject' );
229
 
230
  $woocommerce->mailer()->emails['WC_Email_New_Order']->recipient = $recipient;
231
 
@@ -242,24 +246,20 @@ class WCML_Emails{
242
  }
243
  }
244
 
245
- function filter_payment_method_string( $check, $object_id, $meta_key, $single ){
246
- if( $meta_key == '_payment_method_title' ){
247
-
248
- $payment_method = get_post_meta( $object_id, '_payment_method', true );
249
 
250
- if( $payment_method ){
251
 
252
- $payment_gateways = WC()->payment_gateways->payment_gateways();
253
- if( isset( $payment_gateways[ $payment_method ] ) ){
254
- $title = $this->woocommerce_wpml->gateways->translate_gateway_title( $payment_gateways[ $payment_method ]->title, $payment_method, $this->sitepress->get_current_language() );
255
 
256
- return $title;
257
- }
258
  }
259
-
260
-
261
  }
262
- return $check;
 
263
  }
264
 
265
  function filter_formatted_items( $formatted_meta, $object ){
@@ -322,17 +322,26 @@ class WCML_Emails{
322
  return $value;
323
  }
324
 
325
- function wcml_get_translated_email_string( $context, $name ){
 
 
326
 
327
- if( version_compare(WPML_ST_VERSION, '2.2.6', '<=' ) ){
 
 
 
 
 
 
 
328
  global $wpdb;
329
 
330
  $result = $wpdb->get_var( $wpdb->prepare( "SELECT value FROM {$wpdb->prefix}icl_strings WHERE context = %s AND name = %s ", $context, $name ) );
331
 
332
- return apply_filters( 'wpml_translate_single_string', $result, $context, $name );
333
  }else{
334
 
335
- return apply_filters( 'wpml_translate_single_string', false, $context, $name );
336
 
337
  }
338
 
@@ -357,6 +366,8 @@ class WCML_Emails{
357
  $context = 'admin_texts_'.$email_string[ 0 ];
358
 
359
  $current_language = $this->woocommerce_wpml->strings->get_string_language( $email_option[ $email_string[ 1 ] ], $context, $name );
 
 
360
  }
361
 
362
  $order_id = apply_filters( 'wcml_send_email_order_id', $order_id );
@@ -495,4 +506,10 @@ class WCML_Emails{
495
  return $countries;
496
  }
497
 
 
 
 
 
 
 
498
  }
9
  function __construct( &$woocommerce_wpml, &$sitepress ) {
10
  $this->woocommerce_wpml = $woocommerce_wpml;
11
  $this->sitepress = $sitepress;
12
+
13
  add_action( 'init', array( $this, 'init' ) );
14
  }
15
 
24
  add_action('woocommerce_new_customer_note_notification', array($this, 'email_heading_note'),9);
25
  add_action('wp_ajax_woocommerce_mark_order_complete',array($this,'email_refresh_in_ajax'),9);
26
 
27
+ add_action( 'woocommerce_order_status_pending_to_processing_notification', array( $this, 'email_heading_processing' ), 9 );
28
+ add_action( 'woocommerce_order_status_pending_to_on-hold_notification', array( $this, 'email_heading_processing' ), 9 );
29
 
30
  //wrappers for email's body
31
  add_action('woocommerce_before_resend_order_emails', array($this, 'email_header'));
77
  ){
78
  add_filter( 'woocommerce_order_items_meta_get_formatted', array( $this, 'filter_formatted_items' ), 10, 2 );
79
  }
80
+
81
+ add_filter( 'woocommerce_allow_send_queued_transactional_email', array( $this, 'send_queued_transactional_email' ), 10, 3 );
82
  }
83
 
84
  function email_refresh_in_ajax(){
163
 
164
  function email_heading_processing($order_id){
165
  global $woocommerce;
 
166
 
167
+ if( class_exists( 'WC_Email_Customer_Processing_Order' ) && isset( $woocommerce->mailer()->emails[ 'WC_Email_Customer_Processing_Order' ] ) ){
168
 
169
+ $woocommerce->mailer()->emails['WC_Email_Customer_Processing_Order']->heading = $this->wcml_get_translated_email_string( 'admin_texts_woocommerce_customer_processing_order_settings', '[woocommerce_customer_processing_order_settings]heading', $order_id );
170
 
171
+ $woocommerce->mailer()->emails['WC_Email_Customer_Processing_Order']->subject = $this->wcml_get_translated_email_string( 'admin_texts_woocommerce_customer_processing_order_settings', '[woocommerce_customer_processing_order_settings]subject', $order_id );
172
  $enabled = $woocommerce->mailer()->emails['WC_Email_Customer_Processing_Order']->enabled;
173
  $woocommerce->mailer()->emails['WC_Email_Customer_Processing_Order']->enabled = false;
174
  $woocommerce->mailer()->emails['WC_Email_Customer_Processing_Order']->trigger($order_id);
175
  $woocommerce->mailer()->emails['WC_Email_Customer_Processing_Order']->enabled = $enabled;
176
+
177
  }
178
  }
179
 
199
 
200
  $woocommerce->mailer()->emails['WC_Email_Customer_Refunded_Order']->heading =
201
  $this->wcml_get_translated_email_string( 'admin_texts_woocommerce_customer_refunded_order_settings',
202
+ '[woocommerce_customer_refunded_order_settings]heading_partial', $order_id );
203
  $woocommerce->mailer()->emails['WC_Email_Customer_Refunded_Order']->subject =
204
  $this->wcml_get_translated_email_string( 'admin_texts_woocommerce_customer_refunded_order_settings',
205
+ '[woocommerce_customer_refunded_order_settings]subject_partial', $order_id );
206
 
207
  $enabled = $woocommerce->mailer()->emails['WC_Email_Customer_Refunded_Order']->enabled;
208
  $woocommerce->mailer()->emails['WC_Email_Customer_Refunded_Order']->enabled = false;
227
 
228
  $this->change_email_language( $user_lang );
229
 
230
+ $woocommerce->mailer()->emails['WC_Email_New_Order']->heading = $this->wcml_get_translated_email_string( 'admin_texts_woocommerce_new_order_settings', '[woocommerce_new_order_settings]heading', $order_id );
231
 
232
+ $woocommerce->mailer()->emails['WC_Email_New_Order']->subject = $this->wcml_get_translated_email_string( 'admin_texts_woocommerce_new_order_settings', '[woocommerce_new_order_settings]subject', $order_id );
233
 
234
  $woocommerce->mailer()->emails['WC_Email_New_Order']->recipient = $recipient;
235
 
246
  }
247
  }
248
 
249
+ function filter_payment_method_string( $title, $object_id, $meta_key, $single ){
 
 
 
250
 
251
+ if( '_payment_method_title' === $meta_key ){
252
 
253
+ remove_filter( 'get_post_metadata', array( $this, 'filter_payment_method_string' ), 10, 4 );
254
+ $payment_gateway = wc_get_payment_gateway_by_order( $object_id );
255
+ add_filter( 'get_post_metadata', array( $this, 'filter_payment_method_string' ), 10, 4 );
256
 
257
+ if( $payment_gateway ){
258
+ $title = $this->woocommerce_wpml->gateways->translate_gateway_title( $payment_gateway->title, $payment_gateway->id, $this->sitepress->get_current_language() );
259
  }
 
 
260
  }
261
+
262
+ return $title;
263
  }
264
 
265
  function filter_formatted_items( $formatted_meta, $object ){
322
  return $value;
323
  }
324
 
325
+ function wcml_get_translated_email_string( $context, $name, $order_id = false ){
326
+
327
+ $language_code = null;
328
 
329
+ if( $order_id ){
330
+ $order_language = get_post_meta( $order_id, 'wpml_language', true );
331
+ if( $order_language ){
332
+ $language_code = $order_language;
333
+ }
334
+ }
335
+
336
+ if( version_compare( $this->sitepress->get_wp_api()->constant( 'WPML_ST_VERSION' ), '2.2.6', '<=' ) ){
337
  global $wpdb;
338
 
339
  $result = $wpdb->get_var( $wpdb->prepare( "SELECT value FROM {$wpdb->prefix}icl_strings WHERE context = %s AND name = %s ", $context, $name ) );
340
 
341
+ return apply_filters( 'wpml_translate_single_string', $result, $context, $name, $language_code );
342
  }else{
343
 
344
+ return apply_filters( 'wpml_translate_single_string', false, $context, $name , $language_code);
345
 
346
  }
347
 
366
  $context = 'admin_texts_'.$email_string[ 0 ];
367
 
368
  $current_language = $this->woocommerce_wpml->strings->get_string_language( $email_option[ $email_string[ 1 ] ], $context, $name );
369
+ }elseif( $this->order_id ){
370
+ $order_id = $this->order_id;
371
  }
372
 
373
  $order_id = apply_filters( 'wcml_send_email_order_id', $order_id );
506
  return $countries;
507
  }
508
 
509
+
510
+ function send_queued_transactional_email( $allow, $filter, $args ){
511
+ $this->order_id = $args[0];
512
+ return $allow;
513
+ }
514
+
515
  }
inc/class-wcml-endpoints.php CHANGED
@@ -30,7 +30,7 @@ class WCML_Endpoints{
30
 
31
  function register_endpoints_translations( $language = null ){
32
 
33
- if( !class_exists( 'woocommerce' ) || !defined( 'ICL_SITEPRESS_VERSION' ) || ICL_PLUGIN_INACTIVE || version_compare( WOOCOMMERCE_VERSION, '2.2', '<' ) ) return false;
34
 
35
  $wc_vars = WC()->query->query_vars;
36
 
@@ -111,6 +111,8 @@ class WCML_Endpoints{
111
  delete_option( 'flush_rules_for_endpoints_translations' );
112
  WC()->query->init_query_vars();
113
  WC()->query->add_endpoints();
 
 
114
  remove_filter( 'gettext_with_context', array( $this->woocommerce_wpml->strings, 'category_base_in_strings_language' ), 99, 3 );
115
  flush_rewrite_rules( false );
116
  add_filter( 'gettext_with_context', array( $this->woocommerce_wpml->strings, 'category_base_in_strings_language' ), 99, 3 );
@@ -150,7 +152,14 @@ class WCML_Endpoints{
150
 
151
  $current_lang = $sitepress->get_current_language();
152
  $page_lang = $sitepress->get_language_for_element( $post->ID, 'post_page');
153
- if( $current_lang != $page_lang && apply_filters( 'translate_object_id', $pid, 'page', false, $page_lang ) == $post->ID ){
 
 
 
 
 
 
 
154
 
155
  $endpoints = WC()->query->get_query_vars();
156
 
@@ -162,7 +171,7 @@ class WCML_Endpoints{
162
  }elseif( $key === 'order-received' ){
163
  $endpoint = get_option( 'woocommerce_checkout_order_received_endpoint' );
164
  }else{
165
- $endpoint = get_option( 'woocommerce_myaccount_'.str_replace( '-','_',$key).'_endpoint' );
166
  }
167
 
168
  $endpoint = apply_filters( 'wcml_endpoint_permalink_filter', $endpoint, $key );
30
 
31
  function register_endpoints_translations( $language = null ){
32
 
33
+ if( !class_exists( 'WooCommerce' ) || !defined( 'ICL_SITEPRESS_VERSION' ) || ICL_PLUGIN_INACTIVE || version_compare( WOOCOMMERCE_VERSION, '2.2', '<' ) ) return false;
34
 
35
  $wc_vars = WC()->query->query_vars;
36
 
111
  delete_option( 'flush_rules_for_endpoints_translations' );
112
  WC()->query->init_query_vars();
113
  WC()->query->add_endpoints();
114
+ WC()->query->query_vars = apply_filters( 'wcml_flush_rules_query_vars', WC()->query->query_vars, $this );
115
+
116
  remove_filter( 'gettext_with_context', array( $this->woocommerce_wpml->strings, 'category_base_in_strings_language' ), 99, 3 );
117
  flush_rewrite_rules( false );
118
  add_filter( 'gettext_with_context', array( $this->woocommerce_wpml->strings, 'category_base_in_strings_language' ), 99, 3 );
152
 
153
  $current_lang = $sitepress->get_current_language();
154
  $page_lang = $sitepress->get_language_for_element( $post->ID, 'post_page');
155
+
156
+ if(
157
+ (
158
+ $current_lang != $page_lang &&
159
+ apply_filters( 'translate_object_id', $pid, 'page', false, $page_lang ) == $post->ID
160
+ ) ||
161
+ apply_filters( 'wcml_endpoint_force_permalink_filter', false, $current_lang, $page_lang )
162
+ ){
163
 
164
  $endpoints = WC()->query->get_query_vars();
165
 
171
  }elseif( $key === 'order-received' ){
172
  $endpoint = get_option( 'woocommerce_checkout_order_received_endpoint' );
173
  }else{
174
+ $endpoint = get_option( 'woocommerce_myaccount_'.str_replace( '-','_',$key).'_endpoint', $endpoint );
175
  }
176
 
177
  $endpoint = apply_filters( 'wcml_endpoint_permalink_filter', $endpoint, $key );
inc/class-wcml-install.php CHANGED
@@ -193,7 +193,7 @@ class WCML_Install{
193
  }
194
 
195
  private static function handle_admin_texts(){
196
- if(class_exists('woocommerce')){
197
  //emails texts
198
  $emails = new WC_Emails();
199
  foreach($emails->emails as $email){
193
  }
194
 
195
  private static function handle_admin_texts(){
196
+ if(class_exists('WooCommerce')){
197
  //emails texts
198
  $emails = new WC_Emails();
199
  foreach($emails->emails as $email){
inc/class-wcml-orders.php CHANGED
@@ -44,6 +44,8 @@ class WCML_Orders{
44
  add_action( 'woocommerce_before_order_itemmeta', array( $this, 'backend_before_order_itemmeta' ), 100, 3 );
45
  add_action( 'woocommerce_after_order_itemmeta', array( $this, 'backend_after_order_itemmeta' ), 100, 3 );
46
 
 
 
47
  }
48
 
49
  function filtered_woocommerce_new_order_note_data($translations, $text, $domain ){
@@ -377,4 +379,39 @@ class WCML_Orders{
377
  }
378
 
379
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
380
  }
44
  add_action( 'woocommerce_before_order_itemmeta', array( $this, 'backend_before_order_itemmeta' ), 100, 3 );
45
  add_action( 'woocommerce_after_order_itemmeta', array( $this, 'backend_after_order_itemmeta' ), 100, 3 );
46
 
47
+ add_filter( 'woocommerce_get_item_downloads', array( $this, 'filter_downloadable_product_items' ), 10, 3 );
48
+ add_filter( 'woocommerce_customer_get_downloadable_products', array( $this, 'filter_customer_get_downloadable_products' ), 10, 3 );
49
  }
50
 
51
  function filtered_woocommerce_new_order_note_data($translations, $text, $domain ){
379
  }
380
 
381
 
382
+ public function filter_downloadable_product_items( $files, $item, $object ){
383
+
384
+ $order_language = get_post_meta( WooCommerce_Functions_Wrapper::get_order_id( $object ), 'wpml_language', true );
385
+
386
+ if( $item['variation_id'] > 0 ){
387
+ $item['variation_id'] = apply_filters( 'translate_object_id', $item['variation_id'], 'product_variation', false, $order_language );
388
+ }else{
389
+ $item['product_id'] = apply_filters( 'translate_object_id', $item['product_id'], 'product', false, $order_language );
390
+ }
391
+
392
+ remove_filter( 'woocommerce_get_item_downloads', array( $this, 'filter_downloadable_product_items' ), 10, 3 );
393
+
394
+ $files = WooCommerce_Functions_Wrapper::get_item_downloads( $object, $item );
395
+
396
+ add_filter( 'woocommerce_get_item_downloads', array( $this, 'filter_downloadable_product_items' ), 10, 3 );
397
+
398
+ return $files;
399
+ }
400
+
401
+ public function filter_customer_get_downloadable_products( $downloads ){
402
+
403
+ foreach( $downloads as $key => $download ){
404
+
405
+ $translated_id = apply_filters( 'translate_object_id', $download['product_id'], get_post_type( $download['product_id'] ), false, $this->sitepress->get_current_language() );
406
+
407
+ if( $translated_id ){
408
+ $downloads[ $key ][ 'product_name' ] = get_the_title( $translated_id );
409
+ }
410
+
411
+ }
412
+
413
+ return $downloads;
414
+ }
415
+
416
+
417
  }
inc/class-wcml-products.php CHANGED
@@ -27,6 +27,10 @@ class WCML_Products{
27
  $this->sitepress = $sitepress;
28
  $this->wpdb = $wpdb;
29
 
 
 
 
 
30
  if( is_admin() ){
31
 
32
  add_filter( 'woocommerce_json_search_found_products', array( $this, 'woocommerce_json_search_found_products' ) );
@@ -40,6 +44,7 @@ class WCML_Products{
40
  }else{
41
  add_filter( 'woocommerce_json_search_found_products', array( $this, 'filter_found_products_by_language' ) );
42
  add_filter( 'woocommerce_related_products_args', array( $this, 'filter_related_products_args' ) );
 
43
  }
44
 
45
  add_filter( 'woocommerce_upsell_crosssell_search_products', array( $this, 'filter_woocommerce_upsell_crosssell_posts_by_language' ) );
@@ -50,6 +55,7 @@ class WCML_Products{
50
 
51
  add_filter( 'wpml_override_is_translator', array( $this, 'wcml_override_is_translator' ), 10, 3 );
52
  add_filter( 'wc_product_has_unique_sku', array( $this, 'check_product_sku' ), 10, 3 );
 
53
  }
54
 
55
  // Check if original product
@@ -89,6 +95,14 @@ class WCML_Products{
89
  return $language;
90
  }
91
 
 
 
 
 
 
 
 
 
92
  public function is_variable_product( $product_id ){
93
  $cache_key = $product_id;
94
  $cache_group = 'is_variable_product';
@@ -573,4 +587,11 @@ class WCML_Products{
573
  return $sku_found;
574
  }
575
 
 
 
 
 
 
 
 
576
  }
27
  $this->sitepress = $sitepress;
28
  $this->wpdb = $wpdb;
29
 
30
+ }
31
+
32
+ public function add_hooks(){
33
+
34
  if( is_admin() ){
35
 
36
  add_filter( 'woocommerce_json_search_found_products', array( $this, 'woocommerce_json_search_found_products' ) );
44
  }else{
45
  add_filter( 'woocommerce_json_search_found_products', array( $this, 'filter_found_products_by_language' ) );
46
  add_filter( 'woocommerce_related_products_args', array( $this, 'filter_related_products_args' ) );
47
+ add_filter( 'woocommerce_shortcode_products_query', array( $this, 'add_lang_to_shortcode_products_query' ) );
48
  }
49
 
50
  add_filter( 'woocommerce_upsell_crosssell_search_products', array( $this, 'filter_woocommerce_upsell_crosssell_posts_by_language' ) );
55
 
56
  add_filter( 'wpml_override_is_translator', array( $this, 'wcml_override_is_translator' ), 10, 3 );
57
  add_filter( 'wc_product_has_unique_sku', array( $this, 'check_product_sku' ), 10, 3 );
58
+
59
  }
60
 
61
  // Check if original product
95
  return $language;
96
  }
97
 
98
+ public function get_original_product_id( $product_id ){
99
+
100
+ $original_product_language = $this->get_original_product_language( $product_id );
101
+ $original_product_id = apply_filters( 'translate_object_id', $product_id, get_post_type( $product_id ), true, $original_product_language );
102
+
103
+ return $original_product_id;
104
+ }
105
+
106
  public function is_variable_product( $product_id ){
107
  $cache_key = $product_id;
108
  $cache_group = 'is_variable_product';
587
  return $sku_found;
588
  }
589
 
590
+ public function add_lang_to_shortcode_products_query( $query_args ){
591
+
592
+ $query_args[ 'lang' ] = $this->sitepress->get_current_language();
593
+
594
+ return $query_args;
595
+ }
596
+
597
  }
inc/class-wcml-resources.php CHANGED
@@ -45,9 +45,6 @@ class WCML_Resources {
45
  wp_enqueue_style( 'wcml-dialogs' );
46
  }
47
 
48
- wp_register_style( 'wcml_admin', WCML_PLUGIN_URL . '/res/css/admin.css', array( 'wp-pointer' ), WCML_VERSION );
49
- wp_enqueue_style( 'wcml_admin' );
50
-
51
  wp_enqueue_style( 'wp-color-picker' );
52
  }
53
 
@@ -55,6 +52,11 @@ class WCML_Resources {
55
  wp_register_style( 'wcml_op', WCML_PLUGIN_URL . '/res/css/options-permalink.css', null, WCML_VERSION );
56
  wp_enqueue_style( 'wcml_op' );
57
  }
 
 
 
 
 
58
  }
59
 
60
  public static function load_management_css() {
@@ -72,13 +74,6 @@ class WCML_Resources {
72
  'jquery-ui-resizable'
73
  ), WCML_VERSION );
74
 
75
- wp_enqueue_script(
76
- 'wcml-pointer',
77
- WCML_PLUGIN_URL . '/res/js/pointer' . WCML_JS_MIN . '.js',
78
- array( 'wp-pointer' ),
79
- WCML_VERSION,
80
- true
81
- );
82
 
83
  wp_register_script( 'jquery-cookie', WCML_PLUGIN_URL . '/res/js/jquery.cookie' . WCML_JS_MIN . '.js', array('jquery'), WCML_VERSION );
84
  wp_register_script( 'wcml-dialogs', WCML_PLUGIN_URL . '/res/js/dialogs' . WCML_JS_MIN . '.js', array('jquery', 'jquery-ui-core', 'jquery-ui-dialog'), WCML_VERSION );
@@ -149,6 +144,15 @@ class WCML_Resources {
149
  'is_currency_switched' => isset( $_GET[ 'wcmlc' ] ) ? 1 : 0
150
  ) );
151
  } elseif( is_admin() ) {
 
 
 
 
 
 
 
 
 
152
  wp_register_script( 'wcml-messages', WCML_PLUGIN_URL . '/res/js/wcml-messages' . WCML_JS_MIN . '.js', array('jquery'), WCML_VERSION );
153
  wp_enqueue_script( 'wcml-messages' );
154
  }
@@ -169,8 +173,8 @@ class WCML_Resources {
169
  wp_localize_script( 'wcml-editor', 'wcml_settings',
170
  array(
171
  'strings' => array(
172
- 'choose' => __( 'Choose a file', 'woocommerce_multilingual' ),
173
- 'save_tooltip' => __( 'At least one of these fields is required: title, content or excerpt', 'woocommerce_multilingual' ),
174
  'resign_tooltip'=> __( 'This translation job will no longer be assigned to you. Other translators will be able take it and continue the translation.', 'woocommerce-multilingual')
175
  ),
176
  'hide_resign' => self::$woocommerce_wpml->products->is_hide_resign_button()
@@ -187,7 +191,7 @@ class WCML_Resources {
187
 
188
  public static function load_tooltip_resources() {
189
 
190
- if ( class_exists( 'woocommerce' ) ) {
191
  wp_register_script( 'jquery-tiptip', WC()->plugin_url() . '/assets/js/jquery-tiptip/jquery.tipTip.min.js', array('jquery'), WC_VERSION, true );
192
  wp_register_script( 'wcml-tooltip-init', WCML_PLUGIN_URL . '/res/js/tooltip_init' . WCML_JS_MIN . '.js', array('jquery'), WCML_VERSION );
193
  wp_enqueue_script( 'jquery-tiptip' );
@@ -213,8 +217,7 @@ class WCML_Resources {
213
  }
214
 
215
  if( $product_id ){
216
- $original_language = self::$woocommerce_wpml->products->get_original_product_language( $product_id );
217
- $original_id = apply_filters( 'translate_object_id', $product_id, 'product', true, $original_language );
218
  $custom_product_sync = get_post_meta( $original_id, 'wcml_sync_files', true );
219
  if( $custom_product_sync && $custom_product_sync == 'self' ) {
220
  $file_path_sync = false;
@@ -247,10 +250,9 @@ class WCML_Resources {
247
  '" style="display: none;position:relative;left:2px;top:2px;">';
248
 
249
  if ( isset($_GET['post']) ) {
250
- $original_language = self::$woocommerce_wpml->products->get_original_product_language( $_GET['post'] );
251
- $original_id = apply_filters( 'translate_object_id', $_GET['post'], 'product', true, $original_language );
252
  } elseif ( isset($_GET['trid']) ) {
253
- $original_id = $sitepress->get_original_element_id_by_trid( $_GET['trid'] );
254
  }
255
 
256
  if ( isset($_GET['lang']) ) {
45
  wp_enqueue_style( 'wcml-dialogs' );
46
  }
47
 
 
 
 
48
  wp_enqueue_style( 'wp-color-picker' );
49
  }
50
 
52
  wp_register_style( 'wcml_op', WCML_PLUGIN_URL . '/res/css/options-permalink.css', null, WCML_VERSION );
53
  wp_enqueue_style( 'wcml_op' );
54
  }
55
+
56
+ if( is_admin() ){
57
+ wp_register_style( 'wcml_admin', WCML_PLUGIN_URL . '/res/css/admin.css', array( 'wp-pointer' ), WCML_VERSION );
58
+ wp_enqueue_style( 'wcml_admin' );
59
+ }
60
  }
61
 
62
  public static function load_management_css() {
74
  'jquery-ui-resizable'
75
  ), WCML_VERSION );
76
 
 
 
 
 
 
 
 
77
 
78
  wp_register_script( 'jquery-cookie', WCML_PLUGIN_URL . '/res/js/jquery.cookie' . WCML_JS_MIN . '.js', array('jquery'), WCML_VERSION );
79
  wp_register_script( 'wcml-dialogs', WCML_PLUGIN_URL . '/res/js/dialogs' . WCML_JS_MIN . '.js', array('jquery', 'jquery-ui-core', 'jquery-ui-dialog'), WCML_VERSION );
144
  'is_currency_switched' => isset( $_GET[ 'wcmlc' ] ) ? 1 : 0
145
  ) );
146
  } elseif( is_admin() ) {
147
+
148
+ wp_enqueue_script(
149
+ 'wcml-pointer',
150
+ WCML_PLUGIN_URL . '/res/js/pointer' . WCML_JS_MIN . '.js',
151
+ array( 'wp-pointer' ),
152
+ WCML_VERSION,
153
+ true
154
+ );
155
+
156
  wp_register_script( 'wcml-messages', WCML_PLUGIN_URL . '/res/js/wcml-messages' . WCML_JS_MIN . '.js', array('jquery'), WCML_VERSION );
157
  wp_enqueue_script( 'wcml-messages' );
158
  }
173
  wp_localize_script( 'wcml-editor', 'wcml_settings',
174
  array(
175
  'strings' => array(
176
+ 'choose' => __( 'Choose a file', 'woocommerce-multilingual' ),
177
+ 'save_tooltip' => __( 'At least one of these fields is required: title, content or excerpt', 'woocommerce-multilingual' ),
178
  'resign_tooltip'=> __( 'This translation job will no longer be assigned to you. Other translators will be able take it and continue the translation.', 'woocommerce-multilingual')
179
  ),
180
  'hide_resign' => self::$woocommerce_wpml->products->is_hide_resign_button()
191
 
192
  public static function load_tooltip_resources() {
193
 
194
+ if ( class_exists( 'WooCommerce' ) && function_exists( 'WC' ) ) {
195
  wp_register_script( 'jquery-tiptip', WC()->plugin_url() . '/assets/js/jquery-tiptip/jquery.tipTip.min.js', array('jquery'), WC_VERSION, true );
196
  wp_register_script( 'wcml-tooltip-init', WCML_PLUGIN_URL . '/res/js/tooltip_init' . WCML_JS_MIN . '.js', array('jquery'), WCML_VERSION );
197
  wp_enqueue_script( 'jquery-tiptip' );
217
  }
218
 
219
  if( $product_id ){
220
+ $original_id = self::$woocommerce_wpml->products->get_original_product_id( $product_id );
 
221
  $custom_product_sync = get_post_meta( $original_id, 'wcml_sync_files', true );
222
  if( $custom_product_sync && $custom_product_sync == 'self' ) {
223
  $file_path_sync = false;
250
  '" style="display: none;position:relative;left:2px;top:2px;">';
251
 
252
  if ( isset($_GET['post']) ) {
253
+ $original_id = self::$woocommerce_wpml->products->get_original_product_id( sanitize_text_field( $_GET['post'] ) );
 
254
  } elseif ( isset($_GET['trid']) ) {
255
+ $original_id = $sitepress->get_original_element_id_by_trid( sanitize_text_field( $_GET['trid'] ) );
256
  }
257
 
258
  if ( isset($_GET['lang']) ) {
inc/class-wcml-troubleshooting.php CHANGED
@@ -2,11 +2,19 @@
2
 
3
  class WCML_Troubleshooting{
4
 
5
- function __construct(){
 
 
6
 
7
- add_action('init', array($this, 'init'));
8
 
 
 
 
 
 
9
  }
 
10
 
11
  function init(){
12
  add_action('wp_ajax_trbl_sync_variations', array($this,'trbl_sync_variations'));
@@ -15,6 +23,7 @@ class WCML_Troubleshooting{
15
  add_action('wp_ajax_trbl_sync_categories', array($this,'trbl_sync_categories'));
16
  add_action('wp_ajax_trbl_duplicate_terms', array($this,'trbl_duplicate_terms'));
17
  add_action('wp_ajax_trbl_fix_product_type_terms', array($this,'trbl_fix_product_type_terms'));
 
18
 
19
  }
20
 
@@ -26,29 +35,32 @@ class WCML_Troubleshooting{
26
 
27
  $nonce = filter_input( INPUT_POST, 'wcml_nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
28
  if(!$nonce || !wp_verify_nonce($nonce, 'trbl_update_count')){
29
- die('Invalid nonce');
30
  }
31
 
32
  $this->wcml_sync_variations_update_option();
33
- echo $this->wcml_count_products_with_variations();
34
 
35
- die();
 
 
 
 
36
  }
37
 
38
  function wcml_sync_variations_update_option(){
39
- global $wpdb;
40
- $get_variation_term_taxonomy_ids = $wpdb->get_var("SELECT tt.term_taxonomy_id FROM $wpdb->terms AS t LEFT JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id WHERE t.name = 'variable'");
41
  $get_variation_term_taxonomy_ids = apply_filters('wcml_variation_term_taxonomy_ids',(array)$get_variation_term_taxonomy_ids);
42
 
43
- $get_variables_products = $wpdb->get_results($wpdb->prepare("SELECT tr.element_id as id,tr.language_code as lang FROM {$wpdb->prefix}icl_translations AS tr LEFT JOIN $wpdb->term_relationships as t ON tr.element_id = t.object_id LEFT JOIN $wpdb->posts AS p ON tr.element_id = p.ID
44
  WHERE p.post_status = 'publish' AND tr.source_language_code is NULL AND tr.element_type = 'post_product' AND t.term_taxonomy_id IN (%s) ORDER BY tr.element_id",join(',',$get_variation_term_taxonomy_ids)),ARRAY_A);
45
 
46
  update_option('wcml_products_to_sync',$get_variables_products);
47
  }
48
 
49
  function wcml_count_products(){
50
- global $wpdb;
51
- $get_products_count = $wpdb->get_var("SELECT count(ID) FROM $wpdb->posts AS p LEFT JOIN {$wpdb->prefix}icl_translations AS tr ON tr.element_id = p.ID WHERE p.post_status = 'publish' AND p.post_type = 'product' AND tr.source_language_code is NULL");
52
  return $get_products_count;
53
  }
54
 
@@ -70,13 +82,11 @@ class WCML_Troubleshooting{
70
 
71
  $nonce = filter_input( INPUT_POST, 'wcml_nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
72
  if(!$nonce || !wp_verify_nonce($nonce, 'trbl_sync_variations')){
73
- die('Invalid nonce');
74
  }
75
 
76
- global $woocommerce_wpml,$wpdb,$sitepress;
77
-
78
  $get_variables_products = get_option('wcml_products_to_sync');
79
- $all_active_lang = $sitepress->get_active_languages();
80
  $unset_keys = array();
81
  $products_for_one_ajax = array_slice($get_variables_products,0,3,true);
82
 
@@ -87,7 +97,7 @@ class WCML_Troubleshooting{
87
  $tr_product_id = apply_filters( 'translate_object_id',$product['id'],'product',false,$language['code']);
88
 
89
  if(!is_null($tr_product_id)){
90
- $woocommerce_wpml->sync_variations_data->sync_product_variations($product['id'],$tr_product_id,$language['code'],false,true);
91
  }
92
  if(!in_array($key,$unset_keys)){
93
  $unset_keys[] = $key;
@@ -109,46 +119,39 @@ class WCML_Troubleshooting{
109
  update_option('_wcml_settings', $wcml_settings);
110
  }
111
 
112
- echo 1;
113
-
114
- die();
115
  }
116
 
117
  function trbl_gallery_images(){
118
  $nonce = filter_input( INPUT_POST, 'wcml_nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
119
  if(!$nonce || !wp_verify_nonce($nonce, 'trbl_gallery_images')){
120
- die('Invalid nonce');
121
  }
122
 
123
- global $woocommerce_wpml;
124
-
125
  $all_products = $this->get_products_needs_gallery_sync( true );
126
 
127
  foreach( $all_products as $product ){
128
- $woocommerce_wpml->media->sync_product_gallery($product->ID);
129
  add_post_meta($product->ID,'gallery_sync',true);
130
  }
131
 
132
- echo 1;
133
-
134
- die();
135
 
136
  }
137
 
138
  function get_products_needs_gallery_sync( $limit = false ){
139
- global $wpdb;
140
 
141
- $sql = "SELECT p.ID FROM $wpdb->posts AS p
142
- LEFT JOIN {$wpdb->prefix}icl_translations AS tr
143
  ON tr.element_id = p.ID
144
  WHERE p.post_status = 'publish' AND p.post_type = 'product' AND tr.source_language_code is NULL
145
- AND ( SELECT COUNT( pm.meta_key ) FROM $wpdb->postmeta AS pm WHERE pm.post_id = p.ID AND pm.meta_key = 'gallery_sync' ) = 0 ";
146
 
147
  if( $limit ){
148
  $sql .= "ORDER BY p.ID LIMIT 5";
149
  }
150
 
151
- $all_products = $wpdb->get_results( $sql );
152
 
153
  return $all_products;
154
  }
@@ -156,17 +159,15 @@ class WCML_Troubleshooting{
156
  function trbl_sync_categories(){
157
  $nonce = filter_input( INPUT_POST, 'wcml_nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
158
  if(!$nonce || !wp_verify_nonce($nonce, 'trbl_sync_categories')){
159
- die('Invalid nonce');
160
  }
161
 
162
- global $sitepress;
163
-
164
  $all_categories = $this->get_product_categories_needs_sync( true );
165
 
166
  foreach($all_categories as $category){
167
  add_option('wcml_sync_category_'.$category->term_taxonomy_id,true);
168
- $trid = $sitepress->get_element_trid($category->term_taxonomy_id,'tax_product_cat');
169
- $translations = $sitepress->get_element_translations($trid,'tax_product_cat');
170
  $type = get_woocommerce_term_meta( $category->term_id, 'display_type',true);
171
  $thumbnail_id = get_woocommerce_term_meta( $category->term_id, 'thumbnail_id',true);
172
  foreach($translations as $translation){
@@ -177,27 +178,24 @@ class WCML_Troubleshooting{
177
  }
178
  }
179
 
180
- echo 1;
181
-
182
- die();
183
 
184
  }
185
 
186
 
187
  function get_product_categories_needs_sync( $limit = false ){
188
- global $wpdb;
189
 
190
- $sql = "SELECT t.term_taxonomy_id,t.term_id,tr.language_code FROM $wpdb->term_taxonomy AS t
191
- LEFT JOIN {$wpdb->prefix}icl_translations AS tr
192
  ON tr.element_id = t.term_taxonomy_id
193
  WHERE t.taxonomy = 'product_cat' AND tr.element_type = 'tax_product_cat' AND tr.source_language_code is NULL
194
- AND ( SELECT COUNT( option_id ) FROM $wpdb->options WHERE option_name = CONCAT( 'wcml_sync_category_',t.term_taxonomy_id ) ) = 0 ";
195
 
196
  if( $limit ){
197
  $sql .= "ORDER BY t.term_taxonomy_id LIMIT 5";
198
  }
199
 
200
- $all_categories = $wpdb->get_results( $sql );
201
 
202
  return $all_categories;
203
  }
@@ -206,15 +204,14 @@ class WCML_Troubleshooting{
206
  function trbl_duplicate_terms(){
207
  $nonce = filter_input( INPUT_POST, 'wcml_nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
208
  if(!$nonce || !wp_verify_nonce($nonce, 'trbl_duplicate_terms')){
209
- die('Invalid nonce');
210
  }
211
- global $sitepress;
212
 
213
  $attr = isset($_POST['attr'])?$_POST['attr']:false;
214
 
215
  $terms = get_terms($attr,'hide_empty=0');
216
  $i = 0;
217
- $languages = $sitepress->get_active_languages();
218
  foreach($terms as $term){
219
  foreach($languages as $language){
220
  $tr_id = apply_filters( 'translate_object_id',$term->term_id, $attr, false, $language['code']);
@@ -239,30 +236,84 @@ class WCML_Troubleshooting{
239
 
240
  $new_term = wp_insert_term( $term_name , $attr, $term_args );
241
  if ( $new_term && !is_wp_error( $new_term ) ) {
242
- $tt_id = $sitepress->get_element_trid( $term->term_taxonomy_id, 'tax_' . $attr );
243
- $sitepress->set_element_language_details( $new_term[ 'term_taxonomy_id' ], 'tax_' . $attr, $tt_id, $language['code'] );
244
  }
245
  }
246
  }
247
 
248
  }
249
 
250
- echo 1;
251
-
252
- die();
253
  }
254
 
255
  function trbl_fix_product_type_terms(){
256
  $nonce = filter_input( INPUT_POST, 'wcml_nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
257
  if(!$nonce || !wp_verify_nonce($nonce, 'trbl_product_type_terms')){
258
- die('Invalid nonce');
259
  }
260
 
261
  WCML_Install::check_product_type_terms();
262
 
263
- echo 1;
 
264
 
265
- die();
 
 
 
 
266
  }
267
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
268
  }
2
 
3
  class WCML_Troubleshooting{
4
 
5
+ private $woocommerce_wpml;
6
+ private $sitepress;
7
+ private $wpdb;
8
 
9
+ function __construct( &$woocommerce_wpml, &$sitepress, &$wpdb ){
10
 
11
+ $this->woocommerce_wpml = $woocommerce_wpml;
12
+ $this->sitepress = $sitepress;
13
+ $this->wpdb = $wpdb;
14
+
15
+ add_action( 'init', array( $this, 'init' ) );
16
  }
17
+
18
 
19
  function init(){
20
  add_action('wp_ajax_trbl_sync_variations', array($this,'trbl_sync_variations'));
23
  add_action('wp_ajax_trbl_sync_categories', array($this,'trbl_sync_categories'));
24
  add_action('wp_ajax_trbl_duplicate_terms', array($this,'trbl_duplicate_terms'));
25
  add_action('wp_ajax_trbl_fix_product_type_terms', array($this,'trbl_fix_product_type_terms'));
26
+ add_action( 'wp_ajax_trbl_sync_stock', array( $this, 'trbl_sync_stock' ) );
27
 
28
  }
29
 
35
 
36
  $nonce = filter_input( INPUT_POST, 'wcml_nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
37
  if(!$nonce || !wp_verify_nonce($nonce, 'trbl_update_count')){
38
+ wp_send_json_error('Invalid nonce');
39
  }
40
 
41
  $this->wcml_sync_variations_update_option();
 
42
 
43
+ $result = array(
44
+ 'count' => $this->wcml_count_products_with_variations()
45
+ );
46
+
47
+ wp_send_json_success( $result );
48
  }
49
 
50
  function wcml_sync_variations_update_option(){
51
+
52
+ $get_variation_term_taxonomy_ids = $this->wpdb->get_var("SELECT tt.term_taxonomy_id FROM {$this->wpdb->terms} AS t LEFT JOIN {$this->wpdb->term_taxonomy} AS tt ON t.term_id = tt.term_id WHERE t.name = 'variable'");
53
  $get_variation_term_taxonomy_ids = apply_filters('wcml_variation_term_taxonomy_ids',(array)$get_variation_term_taxonomy_ids);
54
 
55
+ $get_variables_products = $this->wpdb->get_results($this->wpdb->prepare("SELECT tr.element_id as id,tr.language_code as lang FROM {$this->wpdb->prefix}icl_translations AS tr LEFT JOIN {$this->wpdb->term_relationships} as t ON tr.element_id = t.object_id LEFT JOIN {$this->wpdb->posts} AS p ON tr.element_id = p.ID
56
  WHERE p.post_status = 'publish' AND tr.source_language_code is NULL AND tr.element_type = 'post_product' AND t.term_taxonomy_id IN (%s) ORDER BY tr.element_id",join(',',$get_variation_term_taxonomy_ids)),ARRAY_A);
57
 
58
  update_option('wcml_products_to_sync',$get_variables_products);
59
  }
60
 
61
  function wcml_count_products(){
62
+
63
+ $get_products_count = $this->wpdb->get_var("SELECT count(ID) FROM {$this->wpdb->posts} AS p LEFT JOIN {$this->wpdb->prefix}icl_translations AS tr ON tr.element_id = p.ID WHERE p.post_status = 'publish' AND p.post_type = 'product' AND tr.source_language_code is NULL");
64
  return $get_products_count;
65
  }
66
 
82
 
83
  $nonce = filter_input( INPUT_POST, 'wcml_nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
84
  if(!$nonce || !wp_verify_nonce($nonce, 'trbl_sync_variations')){
85
+ wp_send_json_error('Invalid nonce');
86
  }
87
 
 
 
88
  $get_variables_products = get_option('wcml_products_to_sync');
89
+ $all_active_lang = $this->sitepress->get_active_languages();
90
  $unset_keys = array();
91
  $products_for_one_ajax = array_slice($get_variables_products,0,3,true);
92
 
97
  $tr_product_id = apply_filters( 'translate_object_id',$product['id'],'product',false,$language['code']);
98
 
99
  if(!is_null($tr_product_id)){
100
+ $this->woocommerce_wpml->sync_variations_data->sync_product_variations($product['id'],$tr_product_id,$language['code'],false,true);
101
  }
102
  if(!in_array($key,$unset_keys)){
103
  $unset_keys[] = $key;
119
  update_option('_wcml_settings', $wcml_settings);
120
  }
121
 
122
+ wp_send_json_success();
 
 
123
  }
124
 
125
  function trbl_gallery_images(){
126
  $nonce = filter_input( INPUT_POST, 'wcml_nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
127
  if(!$nonce || !wp_verify_nonce($nonce, 'trbl_gallery_images')){
128
+ wp_send_json_error('Invalid nonce');
129
  }
130
 
 
 
131
  $all_products = $this->get_products_needs_gallery_sync( true );
132
 
133
  foreach( $all_products as $product ){
134
+ $this->woocommerce_wpml->media->sync_product_gallery($product->ID);
135
  add_post_meta($product->ID,'gallery_sync',true);
136
  }
137
 
138
+ wp_send_json_success();
 
 
139
 
140
  }
141
 
142
  function get_products_needs_gallery_sync( $limit = false ){
 
143
 
144
+ $sql = "SELECT p.ID FROM {$this->wpdb->posts} AS p
145
+ LEFT JOIN {$this->wpdb->prefix}icl_translations AS tr
146
  ON tr.element_id = p.ID
147
  WHERE p.post_status = 'publish' AND p.post_type = 'product' AND tr.source_language_code is NULL
148
+ AND ( SELECT COUNT( pm.meta_key ) FROM {$this->wpdb->postmeta} AS pm WHERE pm.post_id = p.ID AND pm.meta_key = 'gallery_sync' ) = 0 ";
149
 
150
  if( $limit ){
151
  $sql .= "ORDER BY p.ID LIMIT 5";
152
  }
153
 
154
+ $all_products = $this->wpdb->get_results( $sql );
155
 
156
  return $all_products;
157
  }
159
  function trbl_sync_categories(){
160
  $nonce = filter_input( INPUT_POST, 'wcml_nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
161
  if(!$nonce || !wp_verify_nonce($nonce, 'trbl_sync_categories')){
162
+ wp_send_json_error('Invalid nonce');
163
  }
164
 
 
 
165
  $all_categories = $this->get_product_categories_needs_sync( true );
166
 
167
  foreach($all_categories as $category){
168
  add_option('wcml_sync_category_'.$category->term_taxonomy_id,true);
169
+ $trid = $this->sitepress->get_element_trid($category->term_taxonomy_id,'tax_product_cat');
170
+ $translations = $this->sitepress->get_element_translations($trid,'tax_product_cat');
171
  $type = get_woocommerce_term_meta( $category->term_id, 'display_type',true);
172
  $thumbnail_id = get_woocommerce_term_meta( $category->term_id, 'thumbnail_id',true);
173
  foreach($translations as $translation){
178
  }
179
  }
180
 
181
+ wp_send_json_success();
 
 
182
 
183
  }
184
 
185
 
186
  function get_product_categories_needs_sync( $limit = false ){
 
187
 
188
+ $sql = "SELECT t.term_taxonomy_id,t.term_id,tr.language_code FROM {$this->wpdb->term_taxonomy} AS t
189
+ LEFT JOIN {$this->wpdb->prefix}icl_translations AS tr
190
  ON tr.element_id = t.term_taxonomy_id
191
  WHERE t.taxonomy = 'product_cat' AND tr.element_type = 'tax_product_cat' AND tr.source_language_code is NULL
192
+ AND ( SELECT COUNT( option_id ) FROM {$this->wpdb->options} WHERE option_name = CONCAT( 'wcml_sync_category_',t.term_taxonomy_id ) ) = 0 ";
193
 
194
  if( $limit ){
195
  $sql .= "ORDER BY t.term_taxonomy_id LIMIT 5";
196
  }
197
 
198
+ $all_categories = $this->wpdb->get_results( $sql );
199
 
200
  return $all_categories;
201
  }
204
  function trbl_duplicate_terms(){
205
  $nonce = filter_input( INPUT_POST, 'wcml_nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
206
  if(!$nonce || !wp_verify_nonce($nonce, 'trbl_duplicate_terms')){
207
+ wp_send_json_error('Invalid nonce');
208
  }
 
209
 
210
  $attr = isset($_POST['attr'])?$_POST['attr']:false;
211
 
212
  $terms = get_terms($attr,'hide_empty=0');
213
  $i = 0;
214
+ $languages = $this->sitepress->get_active_languages();
215
  foreach($terms as $term){
216
  foreach($languages as $language){
217
  $tr_id = apply_filters( 'translate_object_id',$term->term_id, $attr, false, $language['code']);
236
 
237
  $new_term = wp_insert_term( $term_name , $attr, $term_args );
238
  if ( $new_term && !is_wp_error( $new_term ) ) {
239
+ $tt_id = $this->sitepress->get_element_trid( $term->term_taxonomy_id, 'tax_' . $attr );
240
+ $this->sitepress->set_element_language_details( $new_term[ 'term_taxonomy_id' ], 'tax_' . $attr, $tt_id, $language['code'] );
241
  }
242
  }
243
  }
244
 
245
  }
246
 
247
+ wp_send_json_success();
 
 
248
  }
249
 
250
  function trbl_fix_product_type_terms(){
251
  $nonce = filter_input( INPUT_POST, 'wcml_nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
252
  if(!$nonce || !wp_verify_nonce($nonce, 'trbl_product_type_terms')){
253
+ wp_send_json_error('Invalid nonce');
254
  }
255
 
256
  WCML_Install::check_product_type_terms();
257
 
258
+ wp_send_json_success();
259
+ }
260
 
261
+ function wcml_count_product_stock_sync(){
262
+
263
+ $results = $this->get_products_needs_stock_sync();
264
+
265
+ return count( $results );
266
  }
267
 
268
+ function trbl_sync_stock(){
269
+
270
+ $nonce = array_key_exists( 'wcml_nonce', $_POST ) ? sanitize_text_field( $_POST[ 'wcml_nonce' ] ) : false;
271
+ if(!$nonce || !wp_verify_nonce($nonce, 'trbl_sync_stock')){
272
+ wp_send_json_error('Invalid nonce');
273
+ }
274
+
275
+ $results = $this->get_products_needs_stock_sync();
276
+
277
+ foreach( $results as $product ){
278
+
279
+ if( get_post_meta( $product->ID, '_manage_stock', true ) === 'yes' ){
280
+
281
+ $translations = $this->sitepress->get_element_translations( $product->trid, $product->element_type );
282
+
283
+ $min_stock = false;
284
+ $stock_status = 'instock';
285
+
286
+ //collect min stock
287
+ foreach( $translations as $translation ){
288
+ $stock = get_post_meta( $translation->element_id, '_stock', true );
289
+ if( !$min_stock || $stock < $min_stock ){
290
+ $min_stock = $stock;
291
+ $stock_status = get_post_meta( $translation->element_id, '_stock_status', true );
292
+ }
293
+ }
294
+
295
+ //update stock value
296
+ foreach( $translations as $translation ){
297
+ update_post_meta( $translation->element_id, '_stock', $min_stock );
298
+ update_post_meta( $translation->element_id, '_stock_status', $stock_status );
299
+ }
300
+ }
301
+ }
302
+
303
+ wp_send_json_success();
304
+ }
305
+
306
+ function get_products_needs_stock_sync(){
307
+
308
+ $results = $this->wpdb->get_results("
309
+ SELECT p.ID, t.trid, t.element_type
310
+ FROM {$this->wpdb->posts} p
311
+ JOIN {$this->wpdb->prefix}icl_translations t ON t.element_id = p.ID AND t.element_type IN ('post_product', 'post_product_variation')
312
+ WHERE p.post_type in ('product', 'product_variation') AND t.source_language_code IS NULL
313
+ ");
314
+
315
+ return $results;
316
+ }
317
+
318
+
319
  }
inc/class-wcml-upgrade.php CHANGED
@@ -537,7 +537,7 @@ class WCML_Upgrade{
537
  function upgrade_4_1_0(){
538
  global $wpdb;
539
 
540
- if( !class_exists( 'woocommerce' ) ){
541
  update_option( '_wcml_4_1_0_migration_required', true );
542
  }else{
543
  $results = $wpdb->get_results("
537
  function upgrade_4_1_0(){
538
  global $wpdb;
539
 
540
+ if( !class_exists( 'WooCommerce' ) ){
541
  update_option( '_wcml_4_1_0_migration_required', true );
542
  }else{
543
  $results = $wpdb->get_results("
inc/class-wcml-url-translation.php CHANGED
@@ -2,822 +2,871 @@
2
 
3
  class WCML_Url_Translation {
4
 
5
- public $default_product_base;
6
- public $default_product_category_base;
7
- public $default_product_category_gettext_base;
8
- public $default_product_tag_base;
9
- public $default_product_tag_gettext_base;
10
-
11
- function __construct() {
12
-
13
- $this->default_product_base = 'product';
14
- $this->default_product_category_base = 'product-category';
15
- $this->default_product_tag_base = 'product-tag';
16
- $this->default_product_category_gettext_base = _x( 'product-category', 'slug', 'woocommerce' );
17
- $this->default_product_tag_gettext_base = _x( 'product-tag', 'slug', 'woocommerce' );
18
-
19
- $this->wc_permalinks = get_option( 'woocommerce_permalinks' );
20
-
21
- $this->set_up(); //initialization
22
-
23
- add_filter( 'pre_update_option_woocommerce_permalinks', array( $this, 'register_product_and_taxonomy_bases' ), 10, 2 );
24
-
25
- add_filter( 'pre_update_option_rewrite_rules', array( $this, 'force_bases_in_strings_languages' ), 1, 1 ); // high priority
26
-
27
- add_filter( 'option_rewrite_rules', array( $this, 'translate_bases_in_rewrite_rules' ), 0, 1 ); // high priority
28
-
29
- add_filter( 'term_link', array( $this, 'translate_taxonomy_base' ), 0, 3 ); // high priority
30
-
31
- add_action( 'init', array( $this, 'fix_post_object_rewrite_slug' ), 6 ); // handle the particular case of the default product base: wpmlst-540
32
-
33
- add_action( 'wp_ajax_wcml_update_base_translation', array( $this, 'wcml_update_base_translation' ) );
34
-
35
- add_filter( 'redirect_canonical', array( $this, 'check_wc_tax_url_on_redirect' ), 10, 2 );
36
-
37
- add_filter( 'query_vars', array( $this, 'translate_query_var_for_product' ) );
38
-
39
- add_filter( 'wp_redirect', array( $this, 'encode_shop_slug' ), 10, 2 );
40
-
41
- }
42
-
43
- function set_up() {
44
- global $woocommerce_wpml;
45
-
46
- if ( empty( $woocommerce_wpml->settings['url_translation_set_up'] ) ) {
47
-
48
- $this->clean_up_product_and_taxonomy_bases();
49
-
50
- //set translate product by default
51
- $this->translate_product_base();
52
 
53
- $this->register_product_and_taxonomy_bases();
 
 
 
 
 
 
 
 
 
 
 
 
 
54
 
55
- $woocommerce_wpml->settings['url_translation_set_up'] = 1;
56
- $woocommerce_wpml->update_settings();
57
- }
58
 
59
- }
60
 
61
- function clean_up_product_and_taxonomy_bases(){
62
- global $wpdb;
63
 
64
- $base = $this->get_woocommerce_product_base();
65
 
66
- //delete other old product bases
67
- $wpdb->query( "DELETE FROM {$wpdb->prefix}icl_strings WHERE context = 'WordPress' AND value != '".trim( $base,'/' )."' AND name LIKE 'URL slug:%' " );
 
68
 
69
- //update name for current base
70
 
71
- $wpdb->update(
72
- $wpdb->prefix . 'icl_strings',
73
- array(
74
- 'context' => 'WordPress',
75
- 'name' => 'URL slug: product'
76
- ),
77
- array(
78
- 'context' => 'WordPress',
79
- 'name' => sprintf('Url slug: %s', trim( $base,'/' ))
80
- )
81
- );
82
 
83
- $woocommerce_permalinks = maybe_unserialize( get_option('woocommerce_permalinks') );
84
 
85
- foreach ( (array) $woocommerce_permalinks as $base_key => $base ) {
 
86
 
87
- $base_key = trim($base_key, '/');
88
 
89
- $taxonomy = false;
 
 
 
 
 
 
 
 
 
 
90
 
91
- switch( $base_key ){
92
- case 'category_base': $taxonomy = 'product_cat'; break;
93
- case 'tag_base': $taxonomy = 'product_tag'; break;
94
- case 'attribute_base':$taxonomy = 'attribute'; break;
95
- }
96
 
97
- if( $taxonomy ) {
98
- $wpdb->query( "DELETE FROM {$wpdb->prefix}icl_strings WHERE context LIKE '".sprintf('URL %s slugs - ', $taxonomy)."%'" );
99
- }
100
 
101
- }
102
 
103
- }
104
 
105
- function fix_post_object_rewrite_slug(){
106
- global $wp_post_types, $wp_rewrite;
 
 
 
 
 
 
 
 
 
107
 
108
- if( empty( $this->wc_permalinks['product_base'] ) ){
 
 
109
 
110
- $wp_post_types['product']->rewrite['slug'] = 'product';
111
- $wp_rewrite->extra_permastructs['product']['struct'] = '/product/%product%';
112
 
113
- }
114
 
115
- }
 
116
 
117
- function url_strings_context() {
118
- return 'WordPress';
119
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
 
121
- public function url_string_name( $type, $value = '' ) {
 
122
 
123
- $name = '';
124
 
125
- switch ( $type ) {
126
- case 'product':
127
- $name = sprintf( 'URL slug: %s', $type );
128
- break;
129
- case 'product_cat':
130
- case 'product_tag':
131
- case 'attribute':
132
- $name = sprintf( 'URL %s tax slug', $type );
133
- break;
134
- case 'attribute_slug':
135
- $name = sprintf( 'URL attribute slug: %s', $value );
136
- break;
137
- }
138
 
139
- return $name;
140
- }
141
 
142
- function translate_product_base() {
143
 
144
- if ( !defined( 'WOOCOMMERCE_VERSION' ) || ( !isset( $GLOBALS['ICL_Pro_Translation'] ) || is_null( $GLOBALS['ICL_Pro_Translation'] ) ) ) {
145
- return;
146
- }
147
 
148
- $slug = $this->get_woocommerce_product_base();
149
 
150
- if ( version_compare( WPML_ST_VERSION, '2.2.6', '>' ) ) {
 
 
 
 
 
 
 
151
 
152
- // Use new API for WPML ST > 2.2.6
153
- do_action( 'wpml_activate_slug_translation', 'product', $slug );
 
 
154
 
155
- } else {
156
 
157
- // force_product_slug_translation_on
158
- global $sitepress;
159
- $iclsettings = $sitepress->get_settings();
160
- if ( empty( $iclsettings['posts_slug_translation']['on'] ) || empty( $iclsettings['posts_slug_translation']['types']['product'] ) ) {
161
- $iclsettings['posts_slug_translation']['on'] = 1;
162
- $iclsettings['posts_slug_translation']['types']['product'] = 1;
163
- $sitepress->save_settings( $iclsettings );
164
- }
165
 
166
- $string = icl_get_string_id( $slug, $this->url_strings_context(), $this->url_string_name( 'product' ) );
167
- if ( !$string ) {
168
- do_action( 'wpml_register_single_string', $this->url_strings_context(), $this->url_string_name( 'product' ), $slug );
169
- }
170
 
171
- }
 
 
 
 
 
 
172
 
173
- }
174
 
175
- function get_woocommerce_product_base() {
 
176
 
177
- if ( isset( $this->wc_permalinks['product_base'] ) && !empty( $this->wc_permalinks['product_base'] ) ) {
178
- return trim( $this->wc_permalinks['product_base'], '/' );
179
- } elseif ( get_option( 'woocommerce_product_slug' ) != false ) {
180
- return trim( get_option( 'woocommerce_product_slug' ), '/' );
181
- } else {
182
- return $this->default_product_base; // the default WooCommerce value. Before permalinks options are saved
183
- }
184
 
185
- }
 
 
186
 
187
- function register_product_and_taxonomy_bases( $value = false, $old_value = false ) {
188
- global $woocommerce_wpml;
 
 
 
189
 
190
- if( empty( $value ) ){
191
- $permalink_options = $this->wc_permalinks;
192
- }else{
193
- $permalink_options = $value;
194
- }
195
 
196
- // products
197
- $product_base = !empty( $permalink_options['product_base'] ) ? trim( $permalink_options['product_base'], '/' ) : $this->default_product_base;
198
- $name = $this->url_string_name( 'product' );
199
 
200
- $string_language = $woocommerce_wpml->strings->get_string_language( $product_base, $this->url_strings_context(), $name );
201
- if( is_null($string_language) ){
202
- $string_language = '';
203
- }
204
- do_action( 'wpml_register_single_string', $this->url_strings_context(), $name, $product_base, false, $string_language );
205
 
206
- if( isset($_POST['product_base_language'])){
207
- $woocommerce_wpml->strings->set_string_language( $product_base, $this->url_strings_context(), $name, $_POST['product_base_language']);
208
- }
 
 
209
 
210
- if ( $product_base == $this->default_product_base ) {
211
- $this->add_default_slug_translations( $product_base, $name );
212
- }
213
 
214
- // categories
215
- $category_base = !empty( $permalink_options['category_base'] ) ? $permalink_options['category_base'] : $this->default_product_category_base;
216
- $name = $this->url_string_name( 'product_cat' );
217
 
218
- $string_language = $woocommerce_wpml->strings->get_string_language( $category_base, $this->url_strings_context(), $name );
219
- if( is_null($string_language) ){
220
- $string_language = '';
221
- }
222
- do_action( 'wpml_register_single_string', $this->url_strings_context(), $name, $category_base, false, $string_language );
223
 
224
- if( isset($_POST['category_base_language'])){
225
- $woocommerce_wpml->strings->set_string_language( $category_base, $this->url_strings_context(), $name, $_POST['category_base_language']);
226
- }
227
-
228
- if ( $category_base == $this->default_product_category_base ) {
229
- $this->add_default_slug_translations( $category_base, $name );
230
- }
231
-
232
- // tags
233
- $tag_base = !empty( $permalink_options['tag_base'] ) ? $permalink_options['tag_base'] : $this->default_product_tag_base;
234
- $name = $this->url_string_name( 'product_tag' );
235
 
236
- $string_language = $woocommerce_wpml->strings->get_string_language( $tag_base, $this->url_strings_context(), $name );
237
- if( is_null($string_language) ){
238
- $string_language = '';
239
- }
240
- do_action( 'wpml_register_single_string', $this->url_strings_context(), $name, $tag_base, false, $string_language );
241
 
242
- if( isset($_POST['tag_base_language'])){
243
- $woocommerce_wpml->strings->set_string_language( $tag_base, $this->url_strings_context(), $name, $_POST['tag_base_language']);
244
- }
245
-
246
- if ( $tag_base == $this->default_product_tag_base ) {
247
- $this->add_default_slug_translations( $tag_base, $name );
248
- }
249
 
250
 
251
- if ( isset( $permalink_options['attribute_base'] ) && $permalink_options['attribute_base'] ) {
252
- $attr_base = trim( $permalink_options['attribute_base'], '/' );
253
-
254
- $string_language = $woocommerce_wpml->strings->get_string_language( $attr_base, $this->url_strings_context(), $name );
255
- if( is_null($string_language) ){
256
- $string_language = '';
257
- }
258
- do_action( 'wpml_register_single_string', $this->url_strings_context(), $this->url_string_name( 'attribute' ), $attr_base, false, $string_language );
259
 
260
- if( isset($_POST['attribute_base_language'])){
261
- $woocommerce_wpml->strings->set_string_language( $attr_base, $this->url_strings_context(), $this->url_string_name( 'attribute' ), $_POST['attribute_base_language']);
262
- }
263
- }
 
264
 
265
- return $value;
266
- }
 
 
267
 
268
- function add_default_slug_translations( $slug, $name ) {
269
- global $woocommerce_wpml, $sitepress, $wpdb;
270
 
271
- $string_id = icl_get_string_id( $slug, $this->url_strings_context(), $name );
272
- $string_language = $woocommerce_wpml->strings->get_string_language( $slug, $this->url_strings_context(), $name );
 
 
 
 
273
 
274
- // will use a filter in the future wpmlst-529
275
- $string_object = new WPML_ST_String( $string_id, $wpdb );
276
- $string_translation_statuses = $string_object->get_translation_statuses();
 
277
 
278
- foreach ( $string_translation_statuses as $s ) {
279
- $string_translations[$s->language] = $s->status;
280
- }
 
 
 
 
 
 
281
 
282
- $languages = $sitepress->get_active_languages();
 
283
 
284
- foreach ( $languages as $language => $language_info ) {
 
285
 
286
- if ( $language != $string_language ) {
 
287
 
288
- // check if there's an existing translation
289
- if ( !isset( $string_translations[$language] ) ) {
 
290
 
291
- $slug_translation = $woocommerce_wpml->strings->get_translation_from_woocommerce_mo_file( $slug, $language, false );
 
 
292
 
293
- if ( $slug_translation ) {
294
- // add string translation
295
- icl_add_string_translation( $string_id, $language, $slug_translation, ICL_STRING_TRANSLATION_COMPLETE );
296
- }
297
 
298
- }
299
 
300
- }
301
- }
302
 
303
- }
 
304
 
305
- function force_bases_in_strings_languages( $value ) {
306
- global $sitepress, $woocommerce_wpml;
307
 
308
- if( $value && $sitepress->get_current_language() != 'en' ) {
 
 
 
309
 
310
- remove_filter( 'gettext_with_context', array( $woocommerce_wpml->strings, 'category_base_in_strings_language' ), 99, 3 );
311
- $taxonomies = array(
312
- 'product_cat' => array(
313
- 'base' => 'category_base',
314
- 'base_translated' => apply_filters(
315
- 'wpml_translate_single_string',
316
- 'product-category',
317
- $this->url_strings_context(),
318
- $this->url_string_name( 'product_cat' )
319
- ),
320
- 'default' => $this->default_product_category_base
321
- ),
322
- 'product_tag' => array(
323
- 'base' => 'tag_base',
324
- 'base_translated' => apply_filters(
325
- 'wpml_translate_single_string',
326
- 'product-tag',
327
- $this->url_strings_context(),
328
- $this->url_string_name( 'product_tag' )
329
- ),
330
- 'default' => $this->default_product_tag_base
331
- ),
332
- );
333
- add_filter( 'gettext_with_context', array( $woocommerce_wpml->strings, 'category_base_in_strings_language' ), 99, 3 );
334
- foreach ( $taxonomies as $taxonomy => $taxonomy_details ) {
335
 
336
- if ( empty( $this->wc_permalinks[$taxonomy_details['base']] ) && $value ) {
 
337
 
338
- $new_value = array();
339
- foreach ( $value as $k => $v ) {
340
- $k = preg_replace( "#" . $taxonomy_details['base_translated'] . "/#", $taxonomy_details['default'] . '/', $k );
341
- $new_value[$k] = $v;
342
- }
343
- $value = $new_value;
344
- unset( $new_value );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
345
 
346
- }
347
 
348
- }
349
 
350
- }
351
 
352
- return $value;
353
 
354
- }
355
 
356
- function translate_bases_in_rewrite_rules( $value ) {
357
- global $sitepress, $sitepress_settings, $woocommerce_wpml;
358
 
359
  if ( ! empty( $value ) ) {
360
 
361
  $taxonomies = array( 'product_cat', 'product_tag' );
362
-
363
  foreach ( $taxonomies as $taxonomy ) {
364
  $slug_details = $this->get_translated_tax_slug( $taxonomy );
365
-
366
  $string_language = $woocommerce_wpml->strings->get_string_language( $slug_details['slug'], $this->url_strings_context(), $this->url_string_name( $taxonomy ) );
367
  if ( $sitepress->get_current_language() == $string_language ) {
368
  continue;
369
  }
370
-
371
  if ( $slug_details ) {
372
-
373
- $slug_match = addslashes( ltrim($slug_details['slug'], '/') );
374
- $slug_translation_match = ltrim($slug_details['translated_slug'], '/');
375
-
376
  $buff_value = array();
377
- foreach ( (array)$value as $k => $v ) {
378
-
 
379
  if ( $slug_details['slug'] != $slug_details['translated_slug'] && preg_match( '#^[^/]*/?' . $slug_match . '/#', $k ) ) {
380
  $k = preg_replace( '#^([^/]*)(/?)' . $slug_match . '/#', '$1$2' . $slug_translation_match . '/', $k );
381
  }
382
-
383
- $buff_value[$k] = $v;
384
  }
385
  $value = $buff_value;
386
  unset( $buff_value );
387
  }
388
-
389
  }
390
-
391
  // handle attributes
392
- $wc_taxonomies = wc_get_attribute_taxonomies();
393
  $wc_taxonomies_wc_format = array();
394
  foreach ( $wc_taxonomies as $k => $v ) {
395
  $wc_taxonomies_wc_format[] = 'pa_' . $v->attribute_name;
396
  }
397
-
398
  foreach ( $wc_taxonomies_wc_format as $taxonomy ) {
399
  $taxonomy_obj = get_taxonomy( $taxonomy );
400
-
401
  if ( isset( $taxonomy_obj->rewrite['slug'] ) ) {
402
- $exp = explode( '/', trim( $taxonomy_obj->rewrite['slug'], '/' ) );
403
  $slug = join( '/', array_slice( $exp, 0, count( $exp ) - 1 ) );
404
 
405
  $attribute_slug = preg_replace( "#^$slug/#", '', $taxonomy_obj->rewrite['slug'] );
406
  }
407
-
408
  if ( isset( $slug ) ) {
409
- $string_language = $woocommerce_wpml->strings->get_string_language($slug, $this->url_strings_context(), $this->url_string_name( 'attribute' ) );
410
-
411
- if ($sitepress->get_current_language() != $string_language) {
412
-
413
- $slug_translation = apply_filters('wpml_translate_single_string', $slug, $this->url_strings_context(), $this->url_string_name( 'attribute' ) );
414
- if ($slug_translation) {
415
-
416
- $attribute_slug_translation = apply_filters('wpml_translate_single_string', $attribute_slug, $this->url_strings_context(), $this->url_string_name( 'attribute_slug', $attribute_slug) );
417
-
418
- $slug_match = addslashes( ltrim($slug, '/') );
419
- $slug_translation_match = ltrim($slug_translation, '/');
420
-
421
  $buff_value = array();
422
- foreach ((array)$value as $k => $v) {
423
- if ($slug != $slug_translation && preg_match('#^' . $slug_match . '/(.*)#', $k)) {
424
- $k = preg_replace('#^' . $slug_match . '/(' . $attribute_slug .')/(.*)#', $slug_translation_match . '/' . $attribute_slug_translation . '/$2', $k);
425
  }
426
- $buff_value[$k] = $v;
427
  }
428
-
429
  $value = $buff_value;
430
- unset($buff_value);
431
-
432
  }
433
-
434
  }
435
  }
436
-
437
- }
438
 
 
439
 
440
 
441
  //filter shop page rewrite slug
442
  $current_shop_id = wc_get_page_id( 'shop' );
443
  $default_shop_id = apply_filters( 'translate_object_id', $current_shop_id, 'page', true, $sitepress->get_default_language() );
444
-
445
- if ( is_null( get_post( $current_shop_id ) ) || is_null( get_post( $default_shop_id ) ) )
446
  return $value;
447
-
 
448
  $current_slug = get_post( $current_shop_id )->post_name;
449
  $default_slug = get_post( $default_shop_id )->post_name;
450
-
451
  if ( $current_slug != $default_slug ) {
452
  $buff_value = array();
453
- foreach ( (array)$value as $k => $v ) {
454
-
455
- if( preg_match( '#^' . $default_slug . '/\?\$$#', $k ) ||
456
- preg_match( '#^' . $default_slug . '/\(?feed#', $k ) ||
457
- preg_match( '#^' . $default_slug . '/page#', $k )){
458
-
 
459
  $k = preg_replace( '#^' . $default_slug . '/#', $current_slug . '/', $k );
460
  }
461
-
462
- $buff_value[$k] = $v;
463
  }
464
-
465
  $value = $buff_value;
466
  unset( $buff_value );
467
  }
468
  }
469
 
470
- return $value;
471
- }
472
 
473
- function translate_taxonomy_base( $termlink, $term, $taxonomy ) {
474
- global $wp_rewrite, $wpml_term_translations, $sitepress;
475
- static $no_recursion_flag;
476
 
477
- // handles product categories, product tags and attributes
478
 
479
- $wc_taxonomies = wc_get_attribute_taxonomies();
480
- foreach ( $wc_taxonomies as $k => $v ) {
481
- $wc_taxonomies_wc_format[] = 'pa_' . $v->attribute_name;
482
- }
483
 
484
- if ( ( $taxonomy == 'product_cat' || $taxonomy == 'product_tag' || ( !empty( $wc_taxonomies_wc_format ) && in_array( $taxonomy, $wc_taxonomies_wc_format ) ) ) && !$no_recursion_flag ) {
485
 
486
- $cache_key = 'termlink#' . $taxonomy . '#' . $term->term_id;
487
- if ( false && $link = wp_cache_get( $cache_key, 'terms' ) ) {
488
- $termlink = $link;
489
 
490
- } else {
491
 
492
- $no_recursion_flag = false;
493
 
494
- if ( !is_null( $wpml_term_translations ) ) {
495
- $term_language = $term->term_id ? $wpml_term_translations->get_element_lang_code( $term->term_taxonomy_id ) : false;
496
- } else {
497
- $term_language = $term->term_id ? $sitepress->get_language_for_element( $term->term_taxonomy_id, 'tax_' . $taxonomy ) : false;
498
- }
499
 
500
- if ( $term_language ) {
501
 
502
- $slug_details = $this->get_translated_tax_slug( $taxonomy, $term_language, true );
503
 
504
- $base = $slug_details['slug'];
505
- $base_translated = $slug_details['translated_slug'];
506
 
507
- if ( !empty( $base_translated ) && $base_translated != $base && isset( $wp_rewrite->extra_permastructs[$taxonomy] ) ) {
508
 
509
- $buff = $wp_rewrite->extra_permastructs[$taxonomy]['struct'];
510
 
511
- // translate the attribute base
512
- $wp_rewrite->extra_permastructs[$taxonomy]['struct'] = preg_replace( '#^' . $base . '/(.*)#', $base_translated . '/$1', $wp_rewrite->extra_permastructs[$taxonomy]['struct'] );
513
 
514
- // translate the attribute slug
515
- if( isset($this->wc_permalinks['attribute_base']) && $this->wc_permalinks['attribute_base'] === $base ){
516
 
517
- $attribute_slug = preg_replace('#^' . $base . '/([^/]+)/.+$#', '$1', $wp_rewrite->extra_permastructs[$taxonomy]['struct']);
518
- $attribute_slug_default = preg_replace('#^pa_#', '', $taxonomy );
519
- $attribute_slug_translation = apply_filters(
520
- 'wpml_translate_single_string',
521
- $attribute_slug,
522
- $this->url_strings_context(),
523
- $this->url_string_name( 'attribute_slug', $attribute_slug_default ),
524
- $term_language
525
- );
526
 
527
- if( $attribute_slug_translation != $attribute_slug ){
528
- $wp_rewrite->extra_permastructs[$taxonomy]['struct'] = preg_replace(
529
- '#^' . $base_translated . '/([^/]+)/(.+)$#',
530
- $base_translated . '/' . $attribute_slug_translation . '/$2',
531
- $wp_rewrite->extra_permastructs[$taxonomy]['struct']
532
- );
533
- }
534
 
535
- }
536
 
537
 
538
- $no_recursion_flag = true;
539
- $termlink = get_term_link( $term, $taxonomy );
540
 
541
- $wp_rewrite->extra_permastructs[$taxonomy]['struct'] = $buff;
542
 
543
- }
544
 
545
- }
546
 
547
- $no_recursion_flag = false;
548
 
549
- wp_cache_add( $cache_key, $termlink, 'terms', 0 );
550
- }
551
 
552
- }
553
 
554
- return $termlink;
555
- }
556
 
557
- function get_translated_tax_slug( $taxonomy, $language = false, $return_gettext_slug = false ) {
558
- global $sitepress, $woocommerce_wpml;
559
 
560
- switch ( $taxonomy ) {
561
- case 'product_tag':
562
 
563
- if( !empty( $this->wc_permalinks['tag_base'] ) ) {
564
- $slug = $gettext_slug = trim($this->wc_permalinks['tag_base'], '/');
565
- }else{
566
- $slug = 'product-tag';
567
- if( $return_gettext_slug ){
568
- $gettext_slug = $this->default_product_tag_gettext_base;
569
- }
570
- }
571
 
572
- $string_language = $woocommerce_wpml->strings->get_string_language( $slug, $this->url_strings_context(), $this->url_string_name( $taxonomy ) );
573
 
574
- break;
575
 
576
- case 'product_cat':
577
 
578
- if( !empty( $this->wc_permalinks['category_base'] ) ) {
579
- $slug = $gettext_slug = trim( $this->wc_permalinks['category_base'], '/' );
580
- }else{
581
- $slug = 'product-category';
582
- if( $return_gettext_slug ){
583
- $gettext_slug = $this->default_product_category_gettext_base;
584
- }
585
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
586
 
587
- $string_language = $woocommerce_wpml->strings->get_string_language( $slug, $this->url_strings_context(), $this->url_string_name( $taxonomy ) );
 
 
 
 
588
 
589
- break;
 
 
 
 
 
 
590
 
591
- default:
592
- $slug = $gettext_slug = trim( $this->wc_permalinks['attribute_base'], '/' );
 
 
593
 
594
- $string_language = $woocommerce_wpml->strings->get_string_language( $slug, $this->url_strings_context(), $this->url_string_name( 'attribute' ) );
595
 
596
- $taxonomy = 'attribute';
 
597
 
598
- break;
599
- }
 
 
 
600
 
601
- if ( !$language ) {
602
- $language = $sitepress->get_current_language();
603
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
604
 
605
- if ( $slug && $language != 'all' && $language != $string_language ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
606
 
607
- $slug_translation = apply_filters( 'wpml_translate_single_string', $slug, $this->url_strings_context(), $this->url_string_name( $taxonomy ), $language, false );
608
 
609
- return array( 'slug' => $return_gettext_slug ? $gettext_slug : $slug, 'translated_slug' => $slug_translation );
610
- }
611
 
612
- return array( 'slug' => $return_gettext_slug ? $gettext_slug : $slug, 'translated_slug' => $return_gettext_slug && $language != $string_language ? $gettext_slug : $slug );
 
613
 
614
- }
 
 
 
 
 
 
615
 
616
- function get_base_translation ( $base, $language ){
617
- global $woocommerce_wpml;
618
 
619
- // case of attribute slugs
620
- if( strpos( $base, 'attribute_slug-' ) === 0 ){
621
- $slug = preg_replace( '#^attribute_slug-#', '', $base );
622
- $base = 'attribute_slug';
623
- }
624
 
625
- switch ( $base ) {
626
- case 'product':
627
- $slug = $this->get_woocommerce_product_base();
628
- $return['name'] = __('Product Base', 'woocommerce-multilingual');
629
- break;
630
 
631
- case 'product_tag':
632
- $slug = !empty( $this->wc_permalinks['tag_base'] ) ? trim( $this->wc_permalinks['tag_base'], '/' ) : 'product-tag';
633
- $return['name'] = __('Product Tag Base', 'woocommerce-multilingual');
634
- break;
635
 
636
- case 'product_cat':
637
- $slug = !empty( $this->wc_permalinks['category_base'] ) ? trim( $this->wc_permalinks['category_base'], '/' ) : 'product-category';
638
- $return['name'] = __('Product Category Base', 'woocommerce-multilingual');
639
- break;
640
 
641
- case 'attribute':
642
- $slug = trim( $this->wc_permalinks['attribute_base'], '/' );
643
- $return['name'] = __('Product Attribute Base', 'woocommerce-multilingual');
644
- break;
645
 
646
- case 'attribute_slug':
647
- $return['name'] = __('Attribute Slug', 'woocommerce-multilingual');
648
- $string_id = icl_get_string_id( $slug, $this->url_strings_context(), $this->url_string_name( $base, $slug ) );
649
- break;
650
 
651
- default:
652
- $endpoints = WC()->query->query_vars;
653
- $slug = isset( $endpoints[ $base ] ) ? $endpoints[ $base ] : false ;
654
- $return['name'] = sprintf( __('Endpoint: %s', 'woocommerce-multilingual'), $base);
655
- $string_id = icl_get_string_id( $slug, 'WooCommerce Endpoints', $base );
656
- break;
657
- }
658
 
659
- $return['original_value'] = $slug;
660
- if( !isset( $string_id ) ){
661
- $string_id = icl_get_string_id( $slug, $this->url_strings_context(), $this->url_string_name( $base ) );
662
- }
663
- $base_translations = icl_get_string_translations_by_id( $string_id );
664
 
665
- $return['translated_base'] = '';
666
- if( isset($base_translations[$language])){
667
- if( $base_translations[$language]['status'] == ICL_TM_COMPLETE ){
668
- $return['translated_base'] = $base_translations[$language]['value'];
669
- }elseif($base_translations[$language]['status'] == ICL_TM_NEEDS_UPDATE){
670
- $return['translated_base'] = $base_translations[$language]['value'];
671
- $return['needs_update '] = true;
672
- }
673
- }
 
 
 
 
 
 
674
 
675
- return $return;
676
 
677
- }
678
 
679
- function get_source_slug_language( $base ){
680
- global $sitepress, $woocommerce_wpml;
681
 
682
- if( $base == 'shop' ){
683
- $source_language = $sitepress->get_language_for_element( get_option('woocommerce_shop_page_id' ) , 'post_page' );
684
- }elseif( in_array( $base, array( 'product','product_cat','product_tag','attribute') ) ){
685
- $source_language = $woocommerce_wpml->strings->get_string_language( $base, $this->url_strings_context(), $this->url_string_name( $base ) );
686
- }else{
687
- $source_language = $woocommerce_wpml->strings->get_string_language( $base, 'WooCommerce Endpoints', $base );
688
- }
689
 
690
- return $source_language;
691
- }
692
 
 
693
 
694
- function wcml_update_base_translation(){
 
 
695
 
696
- $nonce = filter_input( INPUT_POST, 'wcml_nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
697
- if(!$nonce || !wp_verify_nonce($nonce, 'wcml_update_base_translation')){
698
- die('Invalid nonce');
699
- }
 
 
 
700
 
701
- global $wpdb, $woocommerce_wpml, $sitepress;
 
 
 
702
 
703
- $original_base = $_POST['base'];
704
- $original_base_value = $_POST['base_value'];
705
- $base_translation = $_POST['base_translation'];
706
- $language = $_POST['language'];
707
-
708
- if( $original_base == 'shop' ){
709
- $original_shop_id = get_option('woocommerce_shop_page_id' );
710
- $translated_shop_id = apply_filters( 'translate_object_id', $original_shop_id , 'page', false, $language );
711
-
712
- if( !is_null( $translated_shop_id ) ){
713
-
714
- $trnsl_shop_obj = get_post( $translated_shop_id );
715
- $new_slug = wp_unique_post_slug( sanitize_title( $_POST['base_translation'] ), $translated_shop_id, $trnsl_shop_obj->post_status, $trnsl_shop_obj->post_type, $trnsl_shop_obj->post_parent );
716
- $wpdb->update( $wpdb->posts, array( 'post_name' => $new_slug ), array( 'ID' => $translated_shop_id ) );
717
-
718
- }
719
-
720
- }else{
721
- if( in_array( $original_base, array( 'product','product_cat','product_tag','attribute') ) ) {
722
- $string_id = icl_get_string_id( $original_base_value, $this->url_strings_context(), $this->url_string_name( $original_base ) );
723
- }elseif( strpos( $original_base, 'attribute_slug-' ) === 0 ){
724
- $slug = preg_replace( '#^attribute_slug-#', '', $original_base );
725
- do_action( 'wpml_register_single_string', $this->url_strings_context(), $this->url_string_name( 'attribute_slug', $slug ), $slug );
726
- $string_id = icl_get_string_id( $original_base_value, $this->url_strings_context(), $this->url_string_name( 'attribute_slug', $slug ) );
727
- }else{
728
- $string_id = icl_get_string_id( $original_base_value, 'WooCommerce Endpoints', $original_base );
729
- if( !$string_id && function_exists( 'icl_register_string' ) ){
730
- $string_id = icl_register_string( 'WooCommerce Endpoints', $original_base, $original_base_value );
731
- }
732
- $woocommerce_wpml->endpoints->add_endpoints();
733
- $woocommerce_wpml->endpoints->flush_rules_for_endpoints_translations();
734
- }
735
-
736
- icl_add_string_translation( $string_id, $language, $base_translation, ICL_STRING_TRANSLATION_COMPLETE );
737
-
738
- }
739
-
740
- $edit_base = new WCML_Store_URLs_Edit_Base_UI( $original_base, $language, $woocommerce_wpml, $sitepress );
741
- $html = $edit_base->get_view();
742
-
743
- echo json_encode($html);
744
- die();
745
-
746
-
747
- }
748
-
749
- // return correct redirect URL for WC standard taxonomies when pretty permalink uses with lang as parameter in WPML
750
- function check_wc_tax_url_on_redirect( $redirect_url, $requested_url ){
751
- global $wp_query;
752
-
753
- if( is_tax() ){
754
- $original = @parse_url( $requested_url );
755
- if( isset($original['query']) ) {
756
- parse_str( $original['query'], $query_args );
757
- if ( ( isset( $query_args['product_cat'] ) || isset( $query_args['product_tag'] ) ) && isset ( $query_args['lang'] ) ) {
758
- $obj = $wp_query->get_queried_object();
759
- $tax_url = get_term_link( (int) $obj->term_id, $obj->taxonomy );
760
- return $tax_url;
761
- }
762
- }
763
- }
764
 
765
- return $redirect_url;
766
- }
767
 
768
- public function translate_query_var_for_product($public_query_vars){
769
- global $woocommerce_wpml, $sitepress;
770
 
771
- $product_permalink = $woocommerce_wpml->strings->product_permalink_slug();
772
- $string_language = $woocommerce_wpml->strings->get_string_language( $product_permalink, $this->url_strings_context(), $this->url_string_name('product') );
773
 
774
- if( $sitepress->get_current_language() != $string_language ){
775
- $translated_slug = $this->get_translated_product_base_by_lang( false,$product_permalink );
 
 
 
776
 
777
- if(isset($_GET[$translated_slug])){
778
- $buff = $_GET[$translated_slug];
779
- unset($_GET[$translated_slug]);
780
- $_GET[$product_permalink] = $buff;
781
- }
782
 
783
- }
 
784
 
785
- return $public_query_vars;
786
- }
787
 
788
- public function get_translated_product_base_by_lang($language = false, $product_slug = false){
789
- global $woocommerce_wpml;
 
790
 
791
- if(!$language){
792
- global $sitepress;
793
- $language = $sitepress->get_current_language();
794
 
795
- }
 
 
796
 
797
- if(!$product_slug){
798
- $product_slug = $woocommerce_wpml->strings->product_permalink_slug();
799
- }
 
 
 
 
800
 
801
- if ( version_compare( WPML_ST_VERSION, '2.3', '>=' ) ) {
802
- $translated_slug = apply_filters( 'wpml_get_translated_slug', $product_slug, 'product' , $language );
803
- }elseif ( apply_filters( 'wpml_slug_translation_available', false) ) {
804
- $translated_slug = apply_filters( 'wpml_get_translated_slug', 'product' , $language );
805
- } else {
806
- $translated_slug = apply_filters( 'wpml_translate_single_string', $product_slug, $this->url_strings_context(), $this->url_string_name( 'product' ) );
807
- }
808
 
809
- return $translated_slug;
810
- }
 
 
 
811
 
812
- public function encode_shop_slug($location, $status){
813
- if(get_post_type(get_query_var('p')) == 'product'){
814
- global $sitepress;
815
- $language = $sitepress->get_language_for_element(get_query_var('p'), 'post_product');
816
- $base_slug = $this->get_translated_product_base_by_lang($language);
817
 
818
- $location = str_replace($base_slug , urlencode($base_slug),$location);
819
- }
820
-
821
- return $location;
822
- }
823
  }
2
 
3
  class WCML_Url_Translation {
4
 
5
+ public $default_product_base;
6
+ public $default_product_category_base;
7
+ public $default_product_category_gettext_base;
8
+ public $default_product_tag_base;
9
+ public $default_product_tag_gettext_base;
10
+
11
+ function __construct() {
12
+ $this->default_product_base = 'product';
13
+ $this->default_product_category_base = 'product-category';
14
+ $this->default_product_tag_base = 'product-tag';
15
+ $this->default_product_category_gettext_base = _x( 'product-category', 'slug', 'woocommerce' );
16
+ $this->default_product_tag_gettext_base = _x( 'product-tag', 'slug', 'woocommerce' );
17
+ }
18
+
19
+ function set_up() {
20
+ global $woocommerce_wpml;
21
+
22
+ $this->wc_permalinks = get_option( 'woocommerce_permalinks' );
23
+
24
+ add_filter( 'pre_update_option_woocommerce_permalinks', array(
25
+ $this,
26
+ 'register_product_and_taxonomy_bases'
27
+ ), 10, 2 );
28
+
29
+ if ( ! is_admin() ) {
30
+ add_filter( 'option_woocommerce_permalinks', array(
31
+ $this,
32
+ 'use_untranslated_default_url_bases'
33
+ ), 1, 1 ); // avoid using the _x translations
34
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
 
36
+ add_filter( 'pre_update_option_rewrite_rules', array(
37
+ $this,
38
+ 'force_bases_in_strings_languages'
39
+ ), 1, 1 ); // high priority
40
+ add_filter( 'option_rewrite_rules', array( $this, 'translate_bases_in_rewrite_rules' ), 0, 1 ); // high priority
41
+ add_filter( 'term_link', array( $this, 'translate_taxonomy_base' ), 0, 3 ); // high priority
42
+ add_action( 'init', array(
43
+ $this,
44
+ 'fix_post_object_rewrite_slug'
45
+ ), 6 ); // handle the particular case of the default product base: wpmlst-540
46
+ add_action( 'wp_ajax_wcml_update_base_translation', array( $this, 'wcml_update_base_translation' ) );
47
+ add_filter( 'redirect_canonical', array( $this, 'check_wc_tax_url_on_redirect' ), 10, 2 );
48
+ add_filter( 'query_vars', array( $this, 'translate_query_var_for_product' ) );
49
+ add_filter( 'wp_redirect', array( $this, 'encode_shop_slug' ), 10, 2 );
50
 
51
+ if ( empty( $woocommerce_wpml->settings['url_translation_set_up'] ) ) {
 
 
52
 
53
+ $this->clean_up_product_and_taxonomy_bases();
54
 
55
+ //set translate product by default
56
+ $this->translate_product_base();
57
 
58
+ $this->register_product_and_taxonomy_bases();
59
 
60
+ $woocommerce_wpml->settings['url_translation_set_up'] = 1;
61
+ $woocommerce_wpml->update_settings();
62
+ }
63
 
64
+ }
65
 
66
+ function clean_up_product_and_taxonomy_bases() {
67
+ global $wpdb;
 
 
 
 
 
 
 
 
 
68
 
69
+ $base = $this->get_woocommerce_product_base();
70
 
71
+ //delete other old product bases
72
+ $wpdb->query( "DELETE FROM {$wpdb->prefix}icl_strings WHERE context = 'WordPress' AND value != '" . trim( $base, '/' ) . "' AND name LIKE 'URL slug:%' " );
73
 
74
+ //update name for current base
75
 
76
+ $wpdb->update(
77
+ $wpdb->prefix . 'icl_strings',
78
+ array(
79
+ 'context' => 'WordPress',
80
+ 'name' => 'URL slug: product'
81
+ ),
82
+ array(
83
+ 'context' => 'WordPress',
84
+ 'name' => sprintf( 'Url slug: %s', trim( $base, '/' ) )
85
+ )
86
+ );
87
 
88
+ $woocommerce_permalinks = maybe_unserialize( get_option( 'woocommerce_permalinks' ) );
 
 
 
 
89
 
90
+ foreach ( (array) $woocommerce_permalinks as $base_key => $base ) {
 
 
91
 
92
+ $base_key = trim( $base_key, '/' );
93
 
94
+ $taxonomy = false;
95
 
96
+ switch ( $base_key ) {
97
+ case 'category_base':
98
+ $taxonomy = 'product_cat';
99
+ break;
100
+ case 'tag_base':
101
+ $taxonomy = 'product_tag';
102
+ break;
103
+ case 'attribute_base':
104
+ $taxonomy = 'attribute';
105
+ break;
106
+ }
107
 
108
+ if ( $taxonomy ) {
109
+ $wpdb->query( "DELETE FROM {$wpdb->prefix}icl_strings WHERE context LIKE '" . sprintf( 'URL %s slugs - ', $taxonomy ) . "%'" );
110
+ }
111
 
112
+ }
 
113
 
114
+ }
115
 
116
+ function fix_post_object_rewrite_slug() {
117
+ global $wp_post_types, $wp_rewrite;
118
 
119
+ if ( empty( $this->wc_permalinks['product_base'] ) ) {
120
+ $wp_post_types['product']->rewrite['slug'] = 'product';
121
+ if ( empty( $wp_rewrite->extra_permastructs['product']['struct'] ) ) {
122
+ $wp_rewrite->extra_permastructs['product']['struct'] = '/product/%product%';
123
+ }
124
+ }
125
+ }
126
+
127
+ function url_strings_context() {
128
+ return 'WordPress';
129
+ }
130
+
131
+ public function url_string_name( $type, $value = '' ) {
132
+
133
+ $name = '';
134
+
135
+ switch ( $type ) {
136
+ case 'product':
137
+ $name = sprintf( 'URL slug: %s', $type );
138
+ break;
139
+ case 'product_cat':
140
+ case 'product_tag':
141
+ case 'attribute':
142
+ $name = sprintf( 'URL %s tax slug', $type );
143
+ break;
144
+ case 'attribute_slug':
145
+ $name = sprintf( 'URL attribute slug: %s', $value );
146
+ break;
147
+ }
148
 
149
+ return $name;
150
+ }
151
 
152
+ function translate_product_base() {
153
 
154
+ if ( ! defined( 'WOOCOMMERCE_VERSION' ) || ( ! isset( $GLOBALS['ICL_Pro_Translation'] ) || is_null( $GLOBALS['ICL_Pro_Translation'] ) ) ) {
155
+ return;
156
+ }
 
 
 
 
 
 
 
 
 
 
157
 
158
+ $slug = $this->get_woocommerce_product_base();
 
159
 
160
+ if ( version_compare( WPML_ST_VERSION, '2.2.6', '>' ) ) {
161
 
162
+ // Use new API for WPML ST > 2.2.6
163
+ do_action( 'wpml_activate_slug_translation', 'product', $slug );
 
164
 
165
+ } else {
166
 
167
+ // force_product_slug_translation_on
168
+ global $sitepress;
169
+ $iclsettings = $sitepress->get_settings();
170
+ if ( empty( $iclsettings['posts_slug_translation']['on'] ) || empty( $iclsettings['posts_slug_translation']['types']['product'] ) ) {
171
+ $iclsettings['posts_slug_translation']['on'] = 1;
172
+ $iclsettings['posts_slug_translation']['types']['product'] = 1;
173
+ $sitepress->save_settings( $iclsettings );
174
+ }
175
 
176
+ $string = icl_get_string_id( $slug, $this->url_strings_context(), $this->url_string_name( 'product' ) );
177
+ if ( ! $string ) {
178
+ do_action( 'wpml_register_single_string', $this->url_strings_context(), $this->url_string_name( 'product' ), $slug );
179
+ }
180
 
181
+ }
182
 
183
+ }
 
 
 
 
 
 
 
184
 
185
+ function get_woocommerce_product_base() {
 
 
 
186
 
187
+ if ( isset( $this->wc_permalinks['product_base'] ) && ! empty( $this->wc_permalinks['product_base'] ) ) {
188
+ return trim( $this->wc_permalinks['product_base'], '/' );
189
+ } elseif ( get_option( 'woocommerce_product_slug' ) != false ) {
190
+ return trim( get_option( 'woocommerce_product_slug' ), '/' );
191
+ } else {
192
+ return $this->default_product_base; // the default WooCommerce value. Before permalinks options are saved
193
+ }
194
 
195
+ }
196
 
197
+ function register_product_and_taxonomy_bases( $value = false, $old_value = false ) {
198
+ global $woocommerce_wpml;
199
 
200
+ if ( empty( $value ) ) {
201
+ $permalink_options = $this->wc_permalinks;
202
+ } else {
203
+ $permalink_options = $value;
204
+ }
 
 
205
 
206
+ // products
207
+ $product_base = ! empty( $permalink_options['product_base'] ) ? trim( $permalink_options['product_base'], '/' ) : $this->default_product_base;
208
+ $name = $this->url_string_name( 'product' );
209
 
210
+ $string_language = $woocommerce_wpml->strings->get_string_language( $product_base, $this->url_strings_context(), $name );
211
+ if ( is_null( $string_language ) ) {
212
+ $string_language = '';
213
+ }
214
+ do_action( 'wpml_register_single_string', $this->url_strings_context(), $name, $product_base, false, $string_language );
215
 
216
+ if ( isset( $_POST['product_base_language'] ) ) {
217
+ $woocommerce_wpml->strings->set_string_language( $product_base, $this->url_strings_context(), $name, $_POST['product_base_language'] );
218
+ }
 
 
219
 
220
+ if ( $product_base == $this->default_product_base ) {
221
+ $this->add_default_slug_translations( $product_base, $name );
222
+ }
223
 
224
+ // categories
225
+ $category_base = ! empty( $permalink_options['category_base'] ) ? $permalink_options['category_base'] : $this->default_product_category_base;
226
+ $name = $this->url_string_name( 'product_cat' );
 
 
227
 
228
+ $string_language = $woocommerce_wpml->strings->get_string_language( $category_base, $this->url_strings_context(), $name );
229
+ if ( is_null( $string_language ) ) {
230
+ $string_language = '';
231
+ }
232
+ do_action( 'wpml_register_single_string', $this->url_strings_context(), $name, $category_base, false, $string_language );
233
 
234
+ if ( isset( $_POST['category_base_language'] ) ) {
235
+ $woocommerce_wpml->strings->set_string_language( $category_base, $this->url_strings_context(), $name, $_POST['category_base_language'] );
236
+ }
237
 
238
+ if ( $category_base == $this->default_product_category_base ) {
239
+ $this->add_default_slug_translations( $category_base, $name );
240
+ }
241
 
242
+ // tags
243
+ $tag_base = ! empty( $permalink_options['tag_base'] ) ? $permalink_options['tag_base'] : $this->default_product_tag_base;
244
+ $name = $this->url_string_name( 'product_tag' );
 
 
245
 
246
+ $string_language = $woocommerce_wpml->strings->get_string_language( $tag_base, $this->url_strings_context(), $name );
247
+ if ( is_null( $string_language ) ) {
248
+ $string_language = '';
249
+ }
250
+ do_action( 'wpml_register_single_string', $this->url_strings_context(), $name, $tag_base, false, $string_language );
 
 
 
 
 
 
251
 
252
+ if ( isset( $_POST['tag_base_language'] ) ) {
253
+ $woocommerce_wpml->strings->set_string_language( $tag_base, $this->url_strings_context(), $name, $_POST['tag_base_language'] );
254
+ }
 
 
255
 
256
+ if ( $tag_base == $this->default_product_tag_base ) {
257
+ $this->add_default_slug_translations( $tag_base, $name );
258
+ }
 
 
 
 
259
 
260
 
261
+ if ( isset( $permalink_options['attribute_base'] ) && $permalink_options['attribute_base'] ) {
262
+ $attr_base = trim( $permalink_options['attribute_base'], '/' );
 
 
 
 
 
 
263
 
264
+ $string_language = $woocommerce_wpml->strings->get_string_language( $attr_base, $this->url_strings_context(), $name );
265
+ if ( is_null( $string_language ) ) {
266
+ $string_language = '';
267
+ }
268
+ do_action( 'wpml_register_single_string', $this->url_strings_context(), $this->url_string_name( 'attribute' ), $attr_base, false, $string_language );
269
 
270
+ if ( isset( $_POST['attribute_base_language'] ) ) {
271
+ $woocommerce_wpml->strings->set_string_language( $attr_base, $this->url_strings_context(), $this->url_string_name( 'attribute' ), $_POST['attribute_base_language'] );
272
+ }
273
+ }
274
 
275
+ return $value;
276
+ }
277
 
278
+ /**
279
+ * @param string $permalinks
280
+ *
281
+ * @return mixed
282
+ */
283
+ function use_untranslated_default_url_bases( $permalinks ) {
284
 
285
+ // exception (index.php in WP permalink structure) #wcml-1939
286
+ if ( preg_match( '#^/?index\.php/#', get_option( 'permalink_structure' ) ) ) {
287
+ return $permalinks;
288
+ }
289
 
290
+ if ( empty( $permalinks['product_base'] ) ) {
291
+ $permalinks['product_base'] = $this->default_product_base;
292
+ }
293
+ if ( empty( $permalinks['category_base'] ) ) {
294
+ $permalinks['category_base'] = $this->default_product_category_base;
295
+ }
296
+ if ( empty( $permalinks['tag_base'] ) ) {
297
+ $permalinks['tag_base'] = $this->default_product_tag_base;
298
+ }
299
 
300
+ return $permalinks;
301
+ }
302
 
303
+ function add_default_slug_translations( $slug, $name ) {
304
+ global $woocommerce_wpml, $sitepress, $wpdb;
305
 
306
+ $string_id = icl_get_string_id( $slug, $this->url_strings_context(), $name );
307
+ $string_language = $woocommerce_wpml->strings->get_string_language( $slug, $this->url_strings_context(), $name );
308
 
309
+ // will use a filter in the future wpmlst-529
310
+ $string_object = new WPML_ST_String( $string_id, $wpdb );
311
+ $string_translation_statuses = $string_object->get_translation_statuses();
312
 
313
+ foreach ( $string_translation_statuses as $s ) {
314
+ $string_translations[ $s->language ] = $s->status;
315
+ }
316
 
317
+ $languages = $sitepress->get_active_languages();
 
 
 
318
 
319
+ foreach ( $languages as $language => $language_info ) {
320
 
321
+ if ( $language != $string_language ) {
 
322
 
323
+ // check if there's an existing translation
324
+ if ( ! isset( $string_translations[ $language ] ) ) {
325
 
326
+ $slug_translation = $woocommerce_wpml->strings->get_translation_from_woocommerce_mo_file( $slug, $language, false );
 
327
 
328
+ if ( $slug_translation ) {
329
+ // add string translation
330
+ icl_add_string_translation( $string_id, $language, $slug_translation, ICL_STRING_TRANSLATION_COMPLETE );
331
+ }
332
 
333
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
334
 
335
+ }
336
+ }
337
 
338
+ }
339
+
340
+ function force_bases_in_strings_languages( $value ) {
341
+ global $sitepress, $woocommerce_wpml;
342
+
343
+ if ( $value && $sitepress->get_current_language() != 'en' ) {
344
+
345
+ remove_filter( 'gettext_with_context', array(
346
+ $woocommerce_wpml->strings,
347
+ 'category_base_in_strings_language'
348
+ ), 99, 3 );
349
+ $taxonomies = array(
350
+ 'product_cat' => array(
351
+ 'base' => 'category_base',
352
+ 'base_translated' => apply_filters(
353
+ 'wpml_translate_single_string',
354
+ 'product-category',
355
+ $this->url_strings_context(),
356
+ $this->url_string_name( 'product_cat' )
357
+ ),
358
+ 'default' => $this->default_product_category_base
359
+ ),
360
+ 'product_tag' => array(
361
+ 'base' => 'tag_base',
362
+ 'base_translated' => apply_filters(
363
+ 'wpml_translate_single_string',
364
+ 'product-tag',
365
+ $this->url_strings_context(),
366
+ $this->url_string_name( 'product_tag' )
367
+ ),
368
+ 'default' => $this->default_product_tag_base
369
+ ),
370
+ );
371
+ add_filter( 'gettext_with_context', array(
372
+ $woocommerce_wpml->strings,
373
+ 'category_base_in_strings_language'
374
+ ), 99, 3 );
375
+ foreach ( $taxonomies as $taxonomy => $taxonomy_details ) {
376
+
377
+ if ( empty( $this->wc_permalinks[ $taxonomy_details['base'] ] ) && $value ) {
378
+
379
+ $new_value = array();
380
+ foreach ( $value as $k => $v ) {
381
+ $k = preg_replace( "#" . $taxonomy_details['base_translated'] . "/#", $taxonomy_details['default'] . '/', $k );
382
+ $new_value[ $k ] = $v;
383
+ }
384
+ $value = $new_value;
385
+ unset( $new_value );
386
 
387
+ }
388
 
389
+ }
390
 
391
+ }
392
 
393
+ return $value;
394
 
395
+ }
396
 
397
+ function translate_bases_in_rewrite_rules( $value ) {
398
+ global $sitepress, $woocommerce_wpml;
399
 
400
  if ( ! empty( $value ) ) {
401
 
402
  $taxonomies = array( 'product_cat', 'product_tag' );
403
+
404
  foreach ( $taxonomies as $taxonomy ) {
405
  $slug_details = $this->get_translated_tax_slug( $taxonomy );
406
+
407
  $string_language = $woocommerce_wpml->strings->get_string_language( $slug_details['slug'], $this->url_strings_context(), $this->url_string_name( $taxonomy ) );
408
  if ( $sitepress->get_current_language() == $string_language ) {
409
  continue;
410
  }
411
+
412
  if ( $slug_details ) {
413
+
414
+ $slug_match = addslashes( ltrim( $slug_details['slug'], '/' ) );
415
+ $slug_translation_match = ltrim( $slug_details['translated_slug'], '/' );
416
+
417
  $buff_value = array();
418
+
419
+ foreach ( (array) $value as $k => $v ) {
420
+
421
  if ( $slug_details['slug'] != $slug_details['translated_slug'] && preg_match( '#^[^/]*/?' . $slug_match . '/#', $k ) ) {
422
  $k = preg_replace( '#^([^/]*)(/?)' . $slug_match . '/#', '$1$2' . $slug_translation_match . '/', $k );
423
  }
424
+
425
+ $buff_value[ $k ] = $v;
426
  }
427
  $value = $buff_value;
428
  unset( $buff_value );
429
  }
430
+
431
  }
432
+
433
  // handle attributes
434
+ $wc_taxonomies = wc_get_attribute_taxonomies();
435
  $wc_taxonomies_wc_format = array();
436
  foreach ( $wc_taxonomies as $k => $v ) {
437
  $wc_taxonomies_wc_format[] = 'pa_' . $v->attribute_name;
438
  }
439
+
440
  foreach ( $wc_taxonomies_wc_format as $taxonomy ) {
441
  $taxonomy_obj = get_taxonomy( $taxonomy );
442
+
443
  if ( isset( $taxonomy_obj->rewrite['slug'] ) ) {
444
+ $exp = explode( '/', trim( $taxonomy_obj->rewrite['slug'], '/' ) );
445
  $slug = join( '/', array_slice( $exp, 0, count( $exp ) - 1 ) );
446
 
447
  $attribute_slug = preg_replace( "#^$slug/#", '', $taxonomy_obj->rewrite['slug'] );
448
  }
449
+
450
  if ( isset( $slug ) ) {
451
+ $string_language = $woocommerce_wpml->strings->get_string_language( $slug, $this->url_strings_context(), $this->url_string_name( 'attribute' ) );
452
+
453
+ if ( $sitepress->get_current_language() != $string_language ) {
454
+
455
+ $slug_translation = apply_filters( 'wpml_translate_single_string', $slug, $this->url_strings_context(), $this->url_string_name( 'attribute' ) );
456
+ if ( $slug_translation ) {
457
+
458
+ $attribute_slug_translation = apply_filters( 'wpml_translate_single_string', $attribute_slug, $this->url_strings_context(), $this->url_string_name( 'attribute_slug', $attribute_slug ) );
459
+
460
+ $slug_match = addslashes( ltrim( $slug, '/' ) );
461
+ $slug_translation_match = ltrim( $slug_translation, '/' );
462
+
463
  $buff_value = array();
464
+ foreach ( (array) $value as $k => $v ) {
465
+ if ( $slug != $slug_translation && preg_match( '#^' . $slug_match . '/(.*)#', $k ) ) {
466
+ $k = preg_replace( '#^' . $slug_match . '/(' . $attribute_slug . ')/(.*)#', $slug_translation_match . '/' . $attribute_slug_translation . '/$2', $k );
467
  }
468
+ $buff_value[ $k ] = $v;
469
  }
470
+
471
  $value = $buff_value;
472
+ unset( $buff_value );
473
+
474
  }
475
+
476
  }
477
  }
 
 
478
 
479
+ }
480
 
481
 
482
  //filter shop page rewrite slug
483
  $current_shop_id = wc_get_page_id( 'shop' );
484
  $default_shop_id = apply_filters( 'translate_object_id', $current_shop_id, 'page', true, $sitepress->get_default_language() );
485
+
486
+ if ( is_null( get_post( $current_shop_id ) ) || is_null( get_post( $default_shop_id ) ) ) {
487
  return $value;
488
+ }
489
+
490
  $current_slug = get_post( $current_shop_id )->post_name;
491
  $default_slug = get_post( $default_shop_id )->post_name;
492
+
493
  if ( $current_slug != $default_slug ) {
494
  $buff_value = array();
495
+ foreach ( (array) $value as $k => $v ) {
496
+
497
+ if ( preg_match( '#^' . $default_slug . '/\?\$$#', $k ) ||
498
+ preg_match( '#^' . $default_slug . '/\(?feed#', $k ) ||
499
+ preg_match( '#^' . $default_slug . '/page#', $k )
500
+ ) {
501
+
502
  $k = preg_replace( '#^' . $default_slug . '/#', $current_slug . '/', $k );
503
  }
504
+
505
+ $buff_value[ $k ] = $v;
506
  }
507
+
508
  $value = $buff_value;
509
  unset( $buff_value );
510
  }
511
  }
512
 
513
+ return $value;
514
+ }
515
 
516
+ function translate_taxonomy_base( $termlink, $term, $taxonomy ) {
517
+ global $wp_rewrite, $wpml_term_translations, $sitepress;
518
+ static $no_recursion_flag;
519
 
520
+ // handles product categories, product tags and attributes
521
 
522
+ $wc_taxonomies = wc_get_attribute_taxonomies();
523
+ foreach ( $wc_taxonomies as $k => $v ) {
524
+ $wc_taxonomies_wc_format[] = 'pa_' . $v->attribute_name;
525
+ }
526
 
527
+ if ( ( $taxonomy == 'product_cat' || $taxonomy == 'product_tag' || ( ! empty( $wc_taxonomies_wc_format ) && in_array( $taxonomy, $wc_taxonomies_wc_format ) ) ) && ! $no_recursion_flag ) {
528
 
529
+ $cache_key = 'termlink#' . $taxonomy . '#' . $term->term_id;
530
+ if ( false && $link = wp_cache_get( $cache_key, 'terms' ) ) {
531
+ $termlink = $link;
532
 
533
+ } else {
534
 
535
+ $no_recursion_flag = false;
536
 
537
+ if ( ! is_null( $wpml_term_translations ) ) {
538
+ $term_language = $term->term_id ? $wpml_term_translations->get_element_lang_code( $term->term_taxonomy_id ) : false;
539
+ } else {
540
+ $term_language = $term->term_id ? $sitepress->get_language_for_element( $term->term_taxonomy_id, 'tax_' . $taxonomy ) : false;
541
+ }
542
 
543
+ if ( $term_language ) {
544
 
545
+ $slug_details = $this->get_translated_tax_slug( $taxonomy, $term_language, true );
546
 
547
+ $base = $slug_details['slug'];
548
+ $base_translated = $slug_details['translated_slug'];
549
 
550
+ if ( ! empty( $base_translated ) && $base_translated != $base && isset( $wp_rewrite->extra_permastructs[ $taxonomy ] ) ) {
551
 
552
+ $buff = $wp_rewrite->extra_permastructs[ $taxonomy ]['struct'];
553
 
554
+ // translate the attribute base
555
+ $wp_rewrite->extra_permastructs[ $taxonomy ]['struct'] = preg_replace( '#^' . $base . '/(.*)#', $base_translated . '/$1', $wp_rewrite->extra_permastructs[ $taxonomy ]['struct'] );
556
 
557
+ // translate the attribute slug
558
+ if ( isset( $this->wc_permalinks['attribute_base'] ) && $this->wc_permalinks['attribute_base'] === $base ) {
559
 
560
+ $attribute_slug = preg_replace( '#^' . $base . '/([^/]+)/.+$#', '$1', $wp_rewrite->extra_permastructs[ $taxonomy ]['struct'] );
561
+ $attribute_slug_default = preg_replace( '#^pa_#', '', $taxonomy );
562
+ $attribute_slug_translation = apply_filters(
563
+ 'wpml_translate_single_string',
564
+ $attribute_slug,
565
+ $this->url_strings_context(),
566
+ $this->url_string_name( 'attribute_slug', $attribute_slug_default ),
567
+ $term_language
568
+ );
569
 
570
+ if ( $attribute_slug_translation != $attribute_slug ) {
571
+ $wp_rewrite->extra_permastructs[ $taxonomy ]['struct'] = preg_replace(
572
+ '#^' . $base_translated . '/([^/]+)/(.+)$#',
573
+ $base_translated . '/' . $attribute_slug_translation . '/$2',
574
+ $wp_rewrite->extra_permastructs[ $taxonomy ]['struct']
575
+ );
576
+ }
577
 
578
+ }
579
 
580
 
581
+ $no_recursion_flag = true;
582
+ $termlink = get_term_link( $term, $taxonomy );
583
 
584
+ $wp_rewrite->extra_permastructs[ $taxonomy ]['struct'] = $buff;
585
 
586
+ }
587
 
588
+ }
589
 
590
+ $no_recursion_flag = false;
591
 
592
+ wp_cache_add( $cache_key, $termlink, 'terms', 0 );
593
+ }
594
 
595
+ }
596
 
597
+ return $termlink;
598
+ }
599
 
600
+ function get_translated_tax_slug( $taxonomy, $language = false, $return_gettext_slug = false ) {
601
+ global $sitepress, $woocommerce_wpml;
602
 
603
+ switch ( $taxonomy ) {
604
+ case 'product_tag':
605
 
606
+ if ( ! empty( $this->wc_permalinks['tag_base'] ) ) {
607
+ $slug = $gettext_slug = trim( $this->wc_permalinks['tag_base'], '/' );
608
+ } else {
609
+ $slug = 'product-tag';
610
+ if ( $return_gettext_slug ) {
611
+ $gettext_slug = $this->default_product_tag_gettext_base;
612
+ }
613
+ }
614
 
615
+ $string_language = $woocommerce_wpml->strings->get_string_language( $slug, $this->url_strings_context(), $this->url_string_name( $taxonomy ) );
616
 
617
+ break;
618
 
619
+ case 'product_cat':
620
 
621
+ if ( ! empty( $this->wc_permalinks['category_base'] ) ) {
622
+ $slug = $gettext_slug = trim( $this->wc_permalinks['category_base'], '/' );
623
+ } else {
624
+ $slug = 'product-category';
625
+ if ( $return_gettext_slug ) {
626
+ $gettext_slug = $this->default_product_category_gettext_base;
627
+ }
628
+ }
629
+
630
+ $string_language = $woocommerce_wpml->strings->get_string_language( $slug, $this->url_strings_context(), $this->url_string_name( $taxonomy ) );
631
+
632
+ break;
633
+
634
+ default:
635
+ $slug = $gettext_slug = trim( $this->wc_permalinks['attribute_base'], '/' );
636
+
637
+ $string_language = $woocommerce_wpml->strings->get_string_language( $slug, $this->url_strings_context(), $this->url_string_name( 'attribute' ) );
638
+
639
+ $taxonomy = 'attribute';
640
+
641
+ break;
642
+ }
643
 
644
+ if ( ! $language ) {
645
+ $language = $sitepress->get_current_language();
646
+ }
647
+
648
+ if ( $slug && $language != 'all' && $language != $string_language ) {
649
 
650
+ $slug_translation = apply_filters( 'wpml_translate_single_string', $slug, $this->url_strings_context(), $this->url_string_name( $taxonomy ), $language, false );
651
+
652
+ return array(
653
+ 'slug' => $return_gettext_slug ? $gettext_slug : $slug,
654
+ 'translated_slug' => $slug_translation
655
+ );
656
+ }
657
 
658
+ return array(
659
+ 'slug' => $return_gettext_slug ? $gettext_slug : $slug,
660
+ 'translated_slug' => $return_gettext_slug && $language != $string_language ? $gettext_slug : $slug
661
+ );
662
 
663
+ }
664
 
665
+ function get_base_translation( $base, $language ) {
666
+ global $woocommerce_wpml;
667
 
668
+ // case of attribute slugs
669
+ if ( strpos( $base, 'attribute_slug-' ) === 0 ) {
670
+ $slug = preg_replace( '#^attribute_slug-#', '', $base );
671
+ $base = 'attribute_slug';
672
+ }
673
 
674
+ switch ( $base ) {
675
+ case 'product':
676
+ $slug = $this->get_woocommerce_product_base();
677
+ $return['name'] = __( 'Product Base', 'woocommerce-multilingual' );
678
+ break;
679
+
680
+ case 'product_tag':
681
+ $slug = ! empty( $this->wc_permalinks['tag_base'] ) ? trim( $this->wc_permalinks['tag_base'], '/' ) : 'product-tag';
682
+ $return['name'] = __( 'Product Tag Base', 'woocommerce-multilingual' );
683
+ break;
684
+
685
+ case 'product_cat':
686
+ $slug = ! empty( $this->wc_permalinks['category_base'] ) ? trim( $this->wc_permalinks['category_base'], '/' ) : 'product-category';
687
+ $return['name'] = __( 'Product Category Base', 'woocommerce-multilingual' );
688
+ break;
689
+
690
+ case 'attribute':
691
+ $slug = trim( $this->wc_permalinks['attribute_base'], '/' );
692
+ $return['name'] = __( 'Product Attribute Base', 'woocommerce-multilingual' );
693
+ break;
694
+
695
+ case 'attribute_slug':
696
+ $return['name'] = __( 'Attribute Slug', 'woocommerce-multilingual' );
697
+ $string_id = icl_get_string_id( $slug, $this->url_strings_context(), $this->url_string_name( $base, $slug ) );
698
+ break;
699
+
700
+ default:
701
+ $endpoints = WC()->query->query_vars;
702
+ $slug = isset( $endpoints[ $base ] ) ? $endpoints[ $base ] : false;
703
+ $return['name'] = sprintf( __( 'Endpoint: %s', 'woocommerce-multilingual' ), $base );
704
+ $string_id = icl_get_string_id( $slug, 'WooCommerce Endpoints', $base );
705
+ break;
706
+ }
707
 
708
+ $return['original_value'] = $slug;
709
+ if ( ! isset( $string_id ) ) {
710
+ $string_id = icl_get_string_id( $slug, $this->url_strings_context(), $this->url_string_name( $base ) );
711
+ }
712
+ $base_translations = icl_get_string_translations_by_id( $string_id );
713
+
714
+ $return['translated_base'] = '';
715
+ if ( isset( $base_translations[ $language ] ) ) {
716
+ if ( $base_translations[ $language ]['status'] == ICL_TM_COMPLETE ) {
717
+ $return['translated_base'] = $base_translations[ $language ]['value'];
718
+ } elseif ( $base_translations[ $language ]['status'] == ICL_TM_NEEDS_UPDATE ) {
719
+ $return['translated_base'] = $base_translations[ $language ]['value'];
720
+ $return['needs_update '] = true;
721
+ }
722
+ }
723
 
724
+ return $return;
725
 
726
+ }
 
727
 
728
+ function get_source_slug_language( $base ) {
729
+ global $sitepress, $woocommerce_wpml;
730
 
731
+ if ( $base == 'shop' ) {
732
+ $source_language = $sitepress->get_language_for_element( get_option( 'woocommerce_shop_page_id' ), 'post_page' );
733
+ } elseif ( in_array( $base, array( 'product', 'product_cat', 'product_tag', 'attribute' ) ) ) {
734
+ $source_language = $woocommerce_wpml->strings->get_string_language( $base, $this->url_strings_context(), $this->url_string_name( $base ) );
735
+ } else {
736
+ $source_language = $woocommerce_wpml->strings->get_string_language( $base, 'WooCommerce Endpoints', $base );
737
+ }
738
 
739
+ return $source_language;
740
+ }
741
 
742
+ function wcml_update_base_translation() {
 
 
 
 
743
 
744
+ $nonce = filter_input( INPUT_POST, 'wcml_nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
745
+ if ( ! $nonce || ! wp_verify_nonce( $nonce, 'wcml_update_base_translation' ) ) {
746
+ die( 'Invalid nonce' );
747
+ }
 
748
 
749
+ global $wpdb, $woocommerce_wpml, $sitepress;
 
 
 
750
 
751
+ $original_base = $_POST['base'];
752
+ $original_base_value = $_POST['base_value'];
753
+ $base_translation = $_POST['base_translation'];
754
+ $language = $_POST['language'];
755
 
756
+ if ( $original_base == 'shop' ) {
757
+ $original_shop_id = get_option( 'woocommerce_shop_page_id' );
758
+ $translated_shop_id = apply_filters( 'translate_object_id', $original_shop_id, 'page', false, $language );
 
759
 
760
+ if ( ! is_null( $translated_shop_id ) ) {
 
 
 
761
 
762
+ $trnsl_shop_obj = get_post( $translated_shop_id );
763
+ $new_slug = wp_unique_post_slug( sanitize_title( $_POST['base_translation'] ), $translated_shop_id, $trnsl_shop_obj->post_status, $trnsl_shop_obj->post_type, $trnsl_shop_obj->post_parent );
764
+ $wpdb->update( $wpdb->posts, array( 'post_name' => $new_slug ), array( 'ID' => $translated_shop_id ) );
 
 
 
 
765
 
766
+ }
 
 
 
 
767
 
768
+ } else {
769
+ if ( in_array( $original_base, array( 'product', 'product_cat', 'product_tag', 'attribute' ) ) ) {
770
+ $string_id = icl_get_string_id( $original_base_value, $this->url_strings_context(), $this->url_string_name( $original_base ) );
771
+ } elseif ( strpos( $original_base, 'attribute_slug-' ) === 0 ) {
772
+ $slug = preg_replace( '#^attribute_slug-#', '', $original_base );
773
+ do_action( 'wpml_register_single_string', $this->url_strings_context(), $this->url_string_name( 'attribute_slug', $slug ), $slug );
774
+ $string_id = icl_get_string_id( $original_base_value, $this->url_strings_context(), $this->url_string_name( 'attribute_slug', $slug ) );
775
+ } else {
776
+ $string_id = icl_get_string_id( $original_base_value, 'WooCommerce Endpoints', $original_base );
777
+ if ( ! $string_id && function_exists( 'icl_register_string' ) ) {
778
+ $string_id = icl_register_string( 'WooCommerce Endpoints', $original_base, $original_base_value );
779
+ }
780
+ $woocommerce_wpml->endpoints->add_endpoints();
781
+ $woocommerce_wpml->endpoints->flush_rules_for_endpoints_translations();
782
+ }
783
 
784
+ icl_add_string_translation( $string_id, $language, $base_translation, ICL_STRING_TRANSLATION_COMPLETE );
785
 
786
+ }
787
 
788
+ $edit_base = new WCML_Store_URLs_Edit_Base_UI( $original_base, $language, $woocommerce_wpml, $sitepress );
789
+ $html = $edit_base->get_view();
790
 
791
+ echo json_encode( $html );
792
+ die();
 
 
 
 
 
793
 
 
 
794
 
795
+ }
796
 
797
+ // return correct redirect URL for WC standard taxonomies when pretty permalink uses with lang as parameter in WPML
798
+ function check_wc_tax_url_on_redirect( $redirect_url, $requested_url ) {
799
+ global $wp_query;
800
 
801
+ if ( is_tax() ) {
802
+ $original = @parse_url( $requested_url );
803
+ if ( isset( $original['query'] ) ) {
804
+ parse_str( $original['query'], $query_args );
805
+ if ( ( isset( $query_args['product_cat'] ) || isset( $query_args['product_tag'] ) ) && isset ( $query_args['lang'] ) ) {
806
+ $obj = $wp_query->get_queried_object();
807
+ $tax_url = get_term_link( (int) $obj->term_id, $obj->taxonomy );
808
 
809
+ return $tax_url;
810
+ }
811
+ }
812
+ }
813
 
814
+ return $redirect_url;
815
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
816
 
817
+ public function translate_query_var_for_product( $public_query_vars ) {
818
+ global $woocommerce_wpml, $sitepress;
819
 
820
+ $product_permalink = $woocommerce_wpml->strings->product_permalink_slug();
821
+ $string_language = $woocommerce_wpml->strings->get_string_language( $product_permalink, $this->url_strings_context(), $this->url_string_name( 'product' ) );
822
 
823
+ if ( $sitepress->get_current_language() != $string_language ) {
824
+ $translated_slug = $this->get_translated_product_base_by_lang( false, $product_permalink );
825
 
826
+ if ( isset( $_GET[ $translated_slug ] ) ) {
827
+ $buff = $_GET[ $translated_slug ];
828
+ unset( $_GET[ $translated_slug ] );
829
+ $_GET[ $product_permalink ] = $buff;
830
+ }
831
 
832
+ }
 
 
 
 
833
 
834
+ return $public_query_vars;
835
+ }
836
 
837
+ public function get_translated_product_base_by_lang( $language = false, $product_slug = false ) {
838
+ global $woocommerce_wpml;
839
 
840
+ if ( ! $language ) {
841
+ global $sitepress;
842
+ $language = $sitepress->get_current_language();
843
 
844
+ }
 
 
845
 
846
+ if ( ! $product_slug ) {
847
+ $product_slug = $woocommerce_wpml->strings->product_permalink_slug();
848
+ }
849
 
850
+ if ( version_compare( WPML_ST_VERSION, '2.3', '>=' ) ) {
851
+ $translated_slug = apply_filters( 'wpml_get_translated_slug', $product_slug, 'product', $language );
852
+ } elseif ( apply_filters( 'wpml_slug_translation_available', false ) ) {
853
+ $translated_slug = apply_filters( 'wpml_get_translated_slug', 'product', $language );
854
+ } else {
855
+ $translated_slug = apply_filters( 'wpml_translate_single_string', $product_slug, $this->url_strings_context(), $this->url_string_name( 'product' ) );
856
+ }
857
 
858
+ return $translated_slug;
859
+ }
 
 
 
 
 
860
 
861
+ public function encode_shop_slug( $location, $status ) {
862
+ if ( get_post_type( get_query_var( 'p' ) ) == 'product' ) {
863
+ global $sitepress;
864
+ $language = $sitepress->get_language_for_element( get_query_var( 'p' ), 'post_product' );
865
+ $base_slug = $this->get_translated_product_base_by_lang( $language );
866
 
867
+ $location = str_replace( $base_slug, urlencode( $base_slug ), $location );
868
+ }
 
 
 
869
 
870
+ return $location;
871
+ }
 
 
 
872
  }
inc/class-wcml-wc-gateways.php CHANGED
@@ -135,19 +135,16 @@ class WCML_WC_Gateways{
135
  )
136
  );
137
 
138
- $st_page = admin_url( 'admin.php?page=' . WPML_ST_FOLDER . '/menu/string-translation.php&context=woocommerce&search='. esc_attr( $setting_value ) );
139
- if( $text_key === 'title' || $payment_gateway->id === 'paypal' ){
140
- $input_type = 'input';
141
- }else{
142
- $input_type = 'textarea';
143
- }
144
  ?>
145
  <script>
146
- var input = jQuery('<?php echo $input_type ?>[name="<?php echo $input_name ?>"]');
147
- if ( input.length ) {
148
  input.parent().append('<div class="translation_controls"></div>');
149
  input.parent().find('.translation_controls').append('<a href="<?php echo $st_page ?>" style="margin-left: 10px"><?php _e('translations', 'woocommerce-multilingual') ?></a>');
150
  jQuery('#<?php echo $gateway_option.'_'.$text_key.'_language_selector' ?>').prependTo( input.parent().find('.translation_controls') );
 
 
151
  }
152
  </script>
153
  <?php }
135
  )
136
  );
137
 
138
+ $st_page = admin_url( 'admin.php?page=' . WPML_ST_FOLDER . '/menu/string-translation.php&context=woocommerce&search='.esc_attr( preg_replace("/[\n\r]/","",$setting_value) ) );
 
 
 
 
 
139
  ?>
140
  <script>
141
+ var input = jQuery('#<?php echo esc_js( $input_name ); ?>');
142
+ if ( input.length > 0 ) {
143
  input.parent().append('<div class="translation_controls"></div>');
144
  input.parent().find('.translation_controls').append('<a href="<?php echo $st_page ?>" style="margin-left: 10px"><?php _e('translations', 'woocommerce-multilingual') ?></a>');
145
  jQuery('#<?php echo $gateway_option.'_'.$text_key.'_language_selector' ?>').prependTo( input.parent().find('.translation_controls') );
146
+ }else{
147
+ jQuery('#<?php echo $gateway_option.'_'.$text_key.'_language_selector' ?>').remove();
148
  }
149
  </script>
150
  <?php }
inc/class-wcml-wc-shipping.php CHANGED
@@ -9,24 +9,26 @@ class WCML_WC_Shipping{
9
 
10
  $this->sitepress = $sitepress;
11
 
12
- add_filter('woocommerce_package_rates', array($this, 'translate_shipping_methods_in_package'));
13
- add_action('woocommerce_tax_rate_added', array($this, 'register_tax_rate_label_string'), 10, 2 );
14
- add_filter('woocommerce_rate_label',array($this,'translate_woocommerce_rate_label'));
15
-
16
- $this->shipping_methods_filters();
17
- add_action('wp_ajax_woocommerce_shipping_zone_methods_save_settings', array( $this, 'save_shipping_zone_method_from_ajax'), 9 );
18
-
19
  $this->current_language = $this->sitepress->get_current_language();
20
  if( $this->current_language == 'all' ){
21
  $this->current_language = $this->sitepress->get_default_language();
22
  }
23
 
24
- add_action( 'icl_save_term_translation', array( $this, 'sync_class_costs_for_new_shipping_classes' ), 100, 2 );
25
 
 
 
 
 
 
 
26
 
 
 
27
  add_filter( 'pre_update_option_woocommerce_flat_rate_settings', array( $this, 'update_woocommerce_shipping_settings_for_class_costs' ) );
28
  add_filter( 'pre_update_option_woocommerce_international_delivery_settings', array( $this, 'update_woocommerce_shipping_settings_for_class_costs' ) );
29
- add_action( 'wp_ajax_woocommerce_shipping_zone_methods_save_settings', array( $this, 'update_woocommerce_shipping_settings_for_class_costs_from_ajax'), 9);
 
30
  }
31
 
32
  function shipping_methods_filters(){
@@ -119,8 +121,17 @@ class WCML_WC_Shipping{
119
  }
120
 
121
  function translate_shipping_method_title( $title, $shipping_id, $language = false ) {
122
- $shipping_id = str_replace( ':', '', $shipping_id );
123
- $title = apply_filters( 'wpml_translate_single_string', $title, 'woocommerce', $shipping_id .'_shipping_method_title', $language ? $language : $this->current_language );
 
 
 
 
 
 
 
 
 
124
 
125
  return $title;
126
  }
@@ -220,7 +231,7 @@ class WCML_WC_Shipping{
220
 
221
  $updated_costs_settings = $this->update_woocommerce_shipping_settings_for_class_costs( $settings );
222
 
223
- $inst_settings = is_array( $inst_settings ) ? array_replace( $inst_settings, $updated_costs_settings ) : $updated_costs_settings;
224
 
225
  return $inst_settings;
226
  }
9
 
10
  $this->sitepress = $sitepress;
11
 
 
 
 
 
 
 
 
12
  $this->current_language = $this->sitepress->get_current_language();
13
  if( $this->current_language == 'all' ){
14
  $this->current_language = $this->sitepress->get_default_language();
15
  }
16
 
17
+ }
18
 
19
+ function add_hooks(){
20
+
21
+ add_action('woocommerce_tax_rate_added', array($this, 'register_tax_rate_label_string'), 10, 2 );
22
+ add_action('wp_ajax_woocommerce_shipping_zone_methods_save_settings', array( $this, 'save_shipping_zone_method_from_ajax'), 9 );
23
+ add_action( 'icl_save_term_translation', array( $this, 'sync_class_costs_for_new_shipping_classes' ), 100, 2 );
24
+ add_action( 'wp_ajax_woocommerce_shipping_zone_methods_save_settings', array( $this, 'update_woocommerce_shipping_settings_for_class_costs_from_ajax'), 9);
25
 
26
+ add_filter('woocommerce_package_rates', array($this, 'translate_shipping_methods_in_package'));
27
+ add_filter('woocommerce_rate_label',array($this,'translate_woocommerce_rate_label'));
28
  add_filter( 'pre_update_option_woocommerce_flat_rate_settings', array( $this, 'update_woocommerce_shipping_settings_for_class_costs' ) );
29
  add_filter( 'pre_update_option_woocommerce_international_delivery_settings', array( $this, 'update_woocommerce_shipping_settings_for_class_costs' ) );
30
+
31
+ $this->shipping_methods_filters();
32
  }
33
 
34
  function shipping_methods_filters(){
121
  }
122
 
123
  function translate_shipping_method_title( $title, $shipping_id, $language = false ) {
124
+
125
+ if( !is_admin() ){
126
+
127
+ $shipping_id = str_replace( ':', '', $shipping_id );
128
+ $translated_title = apply_filters( 'wpml_translate_single_string', $title, 'woocommerce', $shipping_id .'_shipping_method_title', $language ? $language : $this->current_language );
129
+
130
+ if( $translated_title ){
131
+ $title = $translated_title;
132
+ }
133
+
134
+ }
135
 
136
  return $title;
137
  }
231
 
232
  $updated_costs_settings = $this->update_woocommerce_shipping_settings_for_class_costs( $settings );
233
 
234
+ $inst_settings = is_array( $inst_settings ) ? array_merge( $inst_settings, $updated_costs_settings ) : $updated_costs_settings;
235
 
236
  return $inst_settings;
237
  }
inc/class-wcml-wc-strings.php CHANGED
@@ -49,7 +49,7 @@ class WCML_WC_Strings{
49
  $lang = $sitepress->get_user_admin_language( get_current_user_id(), true );
50
  }
51
 
52
- if( $product ){
53
  $product_id = WooCommerce_Functions_Wrapper::get_product_id( $product );
54
  }elseif( is_numeric( $product_obj ) ){
55
  $product_id = $product_obj;
49
  $lang = $sitepress->get_user_admin_language( get_current_user_id(), true );
50
  }
51
 
52
+ if( $product && is_object( $product ) ){
53
  $product_id = WooCommerce_Functions_Wrapper::get_product_id( $product );
54
  }elseif( is_numeric( $product_obj ) ){
55
  $product_id = $product_obj;
inc/class-woocommerce-wpml.php CHANGED
@@ -67,6 +67,7 @@ class woocommerce_wpml {
67
 
68
 
69
  public function __construct(){
 
70
 
71
  $this->settings = $this->get_settings();
72
  $this->currencies = new WCML_Currencies( $this );
@@ -74,10 +75,14 @@ class woocommerce_wpml {
74
 
75
  new WCML_Widgets( $this );
76
 
77
- if ( class_exists( 'woocommerce' ) && 'yes' == get_option( 'woocommerce_api_enabled' ) ) {
78
- global $sitepress;
79
- if ( version_compare( WC()->version, '2.6', '>=' ) ) {
80
- new WCML_REST_API_Support( $this, $sitepress );
 
 
 
 
81
  } else {
82
  new WCML_WooCommerce_Rest_API_Support( $this, $sitepress );
83
  }
@@ -89,6 +94,8 @@ class woocommerce_wpml {
89
  $this->cs_templates = new WCML_Currency_Switcher_Templates( $this );
90
  $this->cs_templates->init_hooks();
91
  }
 
 
92
  }
93
 
94
  /**
@@ -154,7 +161,7 @@ class woocommerce_wpml {
154
  }
155
 
156
  if( is_admin() ) {
157
- $this->troubleshooting = new WCML_Troubleshooting();
158
  $this->links = new WCML_Links($this, $sitepress);
159
  $this->translation_editor = new WCML_Translation_Editor($this, $sitepress, $wpdb);
160
  $this->languages_upgrader = new WCML_Languages_Upgrader;
@@ -165,7 +172,9 @@ class woocommerce_wpml {
165
  }
166
 
167
  $this->sync_product_data = new WCML_Synchronize_Product_Data( $this, $sitepress, $wpdb );
 
168
  $this->products = new WCML_Products( $this, $sitepress, $wpdb );
 
169
  $this->store = new WCML_Store_Pages ($this, $sitepress ) ;
170
  $this->emails = new WCML_Emails( $this, $sitepress );
171
  $this->terms = new WCML_Terms( $this, $sitepress, $wpdb );
@@ -173,9 +182,11 @@ class woocommerce_wpml {
173
  $this->orders = new WCML_Orders( $this, $sitepress );
174
  $this->strings = new WCML_WC_Strings;
175
  $this->shipping = new WCML_WC_Shipping( $sitepress );
 
176
  $this->gateways = new WCML_WC_Gateways( $this, $sitepress );
177
  $this->currencies = new WCML_Currencies( $this );
178
  $this->url_translation = new WCML_Url_Translation ( $this, $sitepress );
 
179
  $this->endpoints = new WCML_Endpoints( $this );
180
  $this->requests = new WCML_Requests;
181
  $this->cart = new WCML_Cart( $this, $sitepress, $woocommerce );
@@ -183,6 +194,7 @@ class woocommerce_wpml {
183
  $this->locale = new WCML_Locale( $this, $sitepress );
184
  $this->media = new WCML_Media( $this, $sitepress, $wpdb );
185
  $this->downloadable = new WCML_Downloadable_Products( $this, $sitepress );
 
186
  $this->reports = new WCML_Reports;
187
  $this->wcml_products_screen = new WCML_Products_Screen_Options();
188
  $this->wcml_products_screen->init();
@@ -199,6 +211,11 @@ class woocommerce_wpml {
199
  add_filter('woocommerce_get_return_url', array('WCML_Links', 'filter_woocommerce_redirect_location'));
200
 
201
  add_action('wp_ajax_wcml_update_setting_ajx', array($this, 'update_setting_ajx'));
 
 
 
 
 
202
  }
203
 
204
  public function get_settings(){
@@ -297,4 +314,5 @@ class woocommerce_wpml {
297
  }
298
 
299
  }
 
300
  }
67
 
68
 
69
  public function __construct(){
70
+ global $sitepress;
71
 
72
  $this->settings = $this->get_settings();
73
  $this->currencies = new WCML_Currencies( $this );
75
 
76
  new WCML_Widgets( $this );
77
 
78
+ if ( class_exists( 'WooCommerce' ) && defined( 'WC_VERSION' ) && 'yes' == get_option( 'woocommerce_api_enabled' ) && ! is_null( $sitepress ) ) {
79
+ if ( version_compare( WC_VERSION, '2.6', '>=' ) && WCML_REST_API_Support::is_rest_api_request() ) {
80
+ if( WCML_REST_API_Support::get_api_request_version() === 1 ) {
81
+ $wcml_rest_api_support = new WCML_REST_API_Support_V1( $this, $sitepress );
82
+ }else{
83
+ $wcml_rest_api_support = new WCML_REST_API_Support( $this, $sitepress );
84
+ }
85
+ $wcml_rest_api_support->initialize();
86
  } else {
87
  new WCML_WooCommerce_Rest_API_Support( $this, $sitepress );
88
  }
94
  $this->cs_templates = new WCML_Currency_Switcher_Templates( $this );
95
  $this->cs_templates->init_hooks();
96
  }
97
+
98
+
99
  }
100
 
101
  /**
161
  }
162
 
163
  if( is_admin() ) {
164
+ $this->troubleshooting = new WCML_Troubleshooting( $this, $sitepress, $wpdb );
165
  $this->links = new WCML_Links($this, $sitepress);
166
  $this->translation_editor = new WCML_Translation_Editor($this, $sitepress, $wpdb);
167
  $this->languages_upgrader = new WCML_Languages_Upgrader;
172
  }
173
 
174
  $this->sync_product_data = new WCML_Synchronize_Product_Data( $this, $sitepress, $wpdb );
175
+ $this->duplicate_product = new WCML_WC_Admin_Duplicate_Product( $this, $sitepress, $wpdb );
176
  $this->products = new WCML_Products( $this, $sitepress, $wpdb );
177
+ $this->products->add_hooks();
178
  $this->store = new WCML_Store_Pages ($this, $sitepress ) ;
179
  $this->emails = new WCML_Emails( $this, $sitepress );
180
  $this->terms = new WCML_Terms( $this, $sitepress, $wpdb );
182
  $this->orders = new WCML_Orders( $this, $sitepress );
183
  $this->strings = new WCML_WC_Strings;
184
  $this->shipping = new WCML_WC_Shipping( $sitepress );
185
+ $this->shipping->add_hooks();
186
  $this->gateways = new WCML_WC_Gateways( $this, $sitepress );
187
  $this->currencies = new WCML_Currencies( $this );
188
  $this->url_translation = new WCML_Url_Translation ( $this, $sitepress );
189
+ $this->url_translation->set_up();
190
  $this->endpoints = new WCML_Endpoints( $this );
191
  $this->requests = new WCML_Requests;
192
  $this->cart = new WCML_Cart( $this, $sitepress, $woocommerce );
194
  $this->locale = new WCML_Locale( $this, $sitepress );
195
  $this->media = new WCML_Media( $this, $sitepress, $wpdb );
196
  $this->downloadable = new WCML_Downloadable_Products( $this, $sitepress );
197
+ $this->page_builders = new WCML_Page_Builders( $sitepress );
198
  $this->reports = new WCML_Reports;
199
  $this->wcml_products_screen = new WCML_Products_Screen_Options();
200
  $this->wcml_products_screen->init();
211
  add_filter('woocommerce_get_return_url', array('WCML_Links', 'filter_woocommerce_redirect_location'));
212
 
213
  add_action('wp_ajax_wcml_update_setting_ajx', array($this, 'update_setting_ajx'));
214
+
215
+ if( is_admin() ){
216
+ $taxonomy_translation_link_filters = new WCML_Taxonomy_Translation_Link_Filters( $this->attributes );
217
+ $taxonomy_translation_link_filters->add_filters();
218
+ }
219
  }
220
 
221
  public function get_settings(){
314
  }
315
 
316
  }
317
+
318
  }
inc/currencies/class-wcml-custom-prices.php CHANGED
@@ -294,8 +294,7 @@ class WCML_Custom_Prices{
294
  isset($this->woocommerce_wpml->settings['display_custom_prices']) &&
295
  $this->woocommerce_wpml->settings['display_custom_prices'] ){
296
 
297
- $orig_lang = $this->woocommerce_wpml->products->get_original_product_language( $variation_id );
298
- $orig_child_id = apply_filters( 'translate_object_id', $variation_id, 'product_variation', true, $orig_lang );
299
 
300
  if( !get_post_meta( $orig_child_id, '_wcml_custom_prices_status', true ) ){
301
  return false;
@@ -380,9 +379,9 @@ class WCML_Custom_Prices{
380
  '_sale_price_dates_to' => $date_to ),
381
  $code
382
  );
383
- $this->update_custom_prices( $post_id, $custom_prices , $code );
384
 
385
- do_action( 'wcml_after_save_custom_prices', $post_id );
386
  }
387
  }
388
  }
294
  isset($this->woocommerce_wpml->settings['display_custom_prices']) &&
295
  $this->woocommerce_wpml->settings['display_custom_prices'] ){
296
 
297
+ $orig_child_id = $this->woocommerce_wpml->products->get_original_product_id( $variation_id );
 
298
 
299
  if( !get_post_meta( $orig_child_id, '_wcml_custom_prices_status', true ) ){
300
  return false;
379
  '_sale_price_dates_to' => $date_to ),
380
  $code
381
  );
382
+ $product_price = $this->update_custom_prices( $post_id, $custom_prices , $code );
383
 
384
+ do_action( 'wcml_after_save_custom_prices', $post_id, $product_price, $custom_prices, $code );
385
  }
386
  }
387
  }
inc/currencies/class-wcml-multi-currency-orders.php CHANGED
@@ -7,8 +7,9 @@ class WCML_Multi_Currency_Orders{
7
  */
8
  private $multi_currency;
9
 
10
- public function __construct( &$multi_currency ){
11
  $this->multi_currency =& $multi_currency;
 
12
 
13
  if( is_admin() ){
14
  add_filter( 'init', array( $this, 'orders_init' ) );
@@ -151,8 +152,8 @@ class WCML_Multi_Currency_Orders{
151
 
152
  if( isset( $_COOKIE[ '_wcml_order_currency' ] ) ){
153
  $currency = get_woocommerce_currency_symbol($_COOKIE[ '_wcml_order_currency' ]);
154
- }elseif( get_post_meta( $_POST['order_id'], '_order_currency' ) ){
155
- $currency = get_woocommerce_currency_symbol( get_post_meta( $_POST['order_id'], '_order_currency', true ) );
156
  }
157
 
158
  if( isset( $_SERVER[ 'HTTP_REFERER' ] ) ){
@@ -246,7 +247,8 @@ class WCML_Multi_Currency_Orders{
246
  $order_currency = get_post_meta( $_POST['order_id'], '_order_currency', true);
247
  }
248
 
249
- $custom_price = get_post_meta( $_POST['item_to_add'], '_price_'.$order_currency, true );
 
250
 
251
  if( !isset( $this->multi_currency->prices ) ){
252
  $this->multi_currency->prices = new WCML_Multi_Currency_Prices( $this->multi_currency );
@@ -268,7 +270,6 @@ class WCML_Multi_Currency_Orders{
268
  $item['line_tax'] = $this->multi_currency->prices->convert_price_amount( $item['line_tax'], $order_currency );
269
  wc_update_order_item_meta( $item_id, '_line_tax', $item['line_tax'] );
270
 
271
- $item->save_meta_data();
272
  return $item;
273
  }
274
 
@@ -362,7 +363,7 @@ class WCML_Multi_Currency_Orders{
362
  $current_screen = get_current_screen();
363
  if( !empty($current_screen) && $current_screen->id == 'shop_order' ){
364
  $order_id = method_exists( $order, 'get_id' ) ? $order->get_id() : $order->id;
365
- $order_currency = get_post_meta( $order_id, 'order_currency', true );
366
  if( empty( $order_currency ) ){
367
  $value = $this->get_order_currency_cookie();
368
  }
7
  */
8
  private $multi_currency;
9
 
10
+ public function __construct( &$multi_currency, &$woocommerce_wpml ){
11
  $this->multi_currency =& $multi_currency;
12
+ $this->woocommerce_wpml =& $woocommerce_wpml;
13
 
14
  if( is_admin() ){
15
  add_filter( 'init', array( $this, 'orders_init' ) );
152
 
153
  if( isset( $_COOKIE[ '_wcml_order_currency' ] ) ){
154
  $currency = get_woocommerce_currency_symbol($_COOKIE[ '_wcml_order_currency' ]);
155
+ }elseif( isset( $_POST[ 'order_id' ] ) && $order_currency = get_post_meta( sanitize_text_field( $_POST[ 'order_id' ] ), '_order_currency', true ) ){
156
+ $currency = get_woocommerce_currency_symbol( $order_currency );
157
  }
158
 
159
  if( isset( $_SERVER[ 'HTTP_REFERER' ] ) ){
247
  $order_currency = get_post_meta( $_POST['order_id'], '_order_currency', true);
248
  }
249
 
250
+ $original_product_id = $this->woocommerce_wpml->products->get_original_product_id( sanitize_text_field( $_POST['item_to_add'][ 0 ] ) );
251
+ $custom_price = get_post_meta( $original_product_id, '_price_'.$order_currency, true );
252
 
253
  if( !isset( $this->multi_currency->prices ) ){
254
  $this->multi_currency->prices = new WCML_Multi_Currency_Prices( $this->multi_currency );
270
  $item['line_tax'] = $this->multi_currency->prices->convert_price_amount( $item['line_tax'], $order_currency );
271
  wc_update_order_item_meta( $item_id, '_line_tax', $item['line_tax'] );
272
 
 
273
  return $item;
274
  }
275
 
363
  $current_screen = get_current_screen();
364
  if( !empty($current_screen) && $current_screen->id == 'shop_order' ){
365
  $order_id = method_exists( $order, 'get_id' ) ? $order->get_id() : $order->id;
366
+ $order_currency = get_post_meta( $order_id, '_order_currency', true );
367
  if( empty( $order_currency ) ){
368
  $value = $this->get_order_currency_cookie();
369
  }
inc/currencies/class-wcml-multi-currency-prices.php CHANGED
@@ -18,7 +18,8 @@ class WCML_Multi_Currency_Prices{
18
  public function __construct( &$multi_currency ){
19
 
20
  $this->multi_currency =& $multi_currency;
21
- if( !is_admin() ) {
 
22
  add_filter('init', array($this, 'prices_init'), 5);
23
 
24
  // Currency and Amount filters
@@ -143,11 +144,17 @@ class WCML_Multi_Currency_Prices{
143
 
144
  if(empty($no_filter) && in_array(get_post_type($object_id), array('product', 'product_variation'))){
145
 
146
- $price_keys = array(
147
- '_price', '_regular_price', '_sale_price',
148
- '_min_variation_price', '_max_variation_price',
149
- '_min_variation_regular_price', '_max_variation_regular_price',
150
- '_min_variation_sale_price', '_max_variation_sale_price');
 
 
 
 
 
 
151
 
152
  if(in_array($meta_key, $price_keys)){
153
  $no_filter = true;
@@ -243,17 +250,7 @@ class WCML_Multi_Currency_Prices{
243
 
244
  // exception - currencies_without_cents
245
  if(in_array($currency, $this->multi_currency->get_currencies_without_cents())){
246
-
247
- if(version_compare(PHP_VERSION, '5.3.0') >= 0){
248
- $amount = round($amount, 0, PHP_ROUND_HALF_UP);
249
- }else{
250
- if($amount - floor($amount) < 0.5){
251
- $amount = floor($amount);
252
- }else{
253
- $amount = ceil($amount);
254
- }
255
- }
256
-
257
  }
258
 
259
  }else{
@@ -282,17 +279,7 @@ class WCML_Multi_Currency_Prices{
282
 
283
  // exception - currencies_without_cents
284
  if(in_array($currency, $this->multi_currency->get_currencies_without_cents())){
285
-
286
- if(version_compare(PHP_VERSION, '5.3.0') >= 0){
287
- $amount = round($amount, 0, PHP_ROUND_HALF_UP);
288
- }else{
289
- if($amount - floor($amount) < 0.5){
290
- $amount = floor($amount);
291
- }else{
292
- $amount = ceil($amount);
293
- }
294
- }
295
-
296
  }
297
 
298
  }else{
@@ -332,15 +319,7 @@ class WCML_Multi_Currency_Prices{
332
  $rounded_price = floor($price);
333
  break;
334
  case 'nearest':
335
- if(version_compare(PHP_VERSION, '5.3.0') >= 0){
336
- $rounded_price = round($price, 0, PHP_ROUND_HALF_UP);
337
- }else{
338
- if($price - floor($price) < 0.5){
339
- $rounded_price = floor($price);
340
- }else{
341
- $rounded_price = ceil($price);
342
- }
343
- }
344
  break;
345
  }
346
 
@@ -368,6 +347,21 @@ class WCML_Multi_Currency_Prices{
368
 
369
  }
370
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
371
  /*
372
  * Converts the price from the default currency to the given currency and applies the format
373
  */
18
  public function __construct( &$multi_currency ){
19
 
20
  $this->multi_currency =& $multi_currency;
21
+
22
+ if( $this->multi_currency->load_filters ) {
23
  add_filter('init', array($this, 'prices_init'), 5);
24
 
25
  // Currency and Amount filters
144
 
145
  if(empty($no_filter) && in_array(get_post_type($object_id), array('product', 'product_variation'))){
146
 
147
+ $price_keys = apply_filters( 'wcml_price_custom_fields_filtered', array(
148
+ '_price',
149
+ '_regular_price',
150
+ '_sale_price',
151
+ '_min_variation_price',
152
+ '_max_variation_price',
153
+ '_min_variation_regular_price',
154
+ '_max_variation_regular_price',
155
+ '_min_variation_sale_price',
156
+ '_max_variation_sale_price'
157
+ ) );
158
 
159
  if(in_array($meta_key, $price_keys)){
160
  $no_filter = true;
250
 
251
  // exception - currencies_without_cents
252
  if(in_array($currency, $this->multi_currency->get_currencies_without_cents())){
253
+ $amount = $this->round_up( $amount );
 
 
 
 
 
 
 
 
 
 
254
  }
255
 
256
  }else{
279
 
280
  // exception - currencies_without_cents
281
  if(in_array($currency, $this->multi_currency->get_currencies_without_cents())){
282
+ $amount = $this->round_up( $amount );
 
 
 
 
 
 
 
 
 
 
283
  }
284
 
285
  }else{
319
  $rounded_price = floor($price);
320
  break;
321
  case 'nearest':
322
+ $rounded_price = $this->round_up( $price );
 
 
 
 
 
 
 
 
323
  break;
324
  }
325
 
347
 
348
  }
349
 
350
+ /**
351
+ * The PHP 5.2 compatible equivalent to "round($amount, 0, PHP_ROUND_HALF_UP)"
352
+ * @param int $amount
353
+ * @return int
354
+ *
355
+ */
356
+ private function round_up( $amount ){
357
+ if( $amount - floor( $amount ) < 0.5 ){
358
+ $amount = floor( $amount );
359
+ }else{
360
+ $amount = ceil( $amount );
361
+ }
362
+ return $amount;
363
+ }
364
+
365
  /*
366
  * Converts the price from the default currency to the given currency and applies the format
367
  */
inc/currencies/class-wcml-multi-currency-resources.php CHANGED
@@ -18,13 +18,11 @@ class WCML_Multi_Currency_Resources{
18
  }
19
 
20
  private static function load_inline_js(){
21
- global $woocommerce_wpml;
22
 
23
  wp_register_script('wcml-mc-scripts', WCML_PLUGIN_URL . '/res/js/wcml-multi-currency' . WCML_JS_MIN . '.js', array('jquery'), WCML_VERSION, true);
24
 
25
  wp_enqueue_script('wcml-mc-scripts');
26
 
27
- $script_vars['wcml_mc_nonce'] = wp_create_nonce( 'switch_currency' );
28
  $script_vars['wcml_spinner'] = WCML_PLUGIN_URL . '/res/images/ajax-loader.gif';
29
  $script_vars['current_currency']= array(
30
  'code' => self::$multi_currency->get_client_currency(),
18
  }
19
 
20
  private static function load_inline_js(){
 
21
 
22
  wp_register_script('wcml-mc-scripts', WCML_PLUGIN_URL . '/res/js/wcml-multi-currency' . WCML_JS_MIN . '.js', array('jquery'), WCML_VERSION, true);
23
 
24
  wp_enqueue_script('wcml-mc-scripts');
25
 
 
26
  $script_vars['wcml_spinner'] = WCML_PLUGIN_URL . '/res/images/ajax-loader.gif';
27
  $script_vars['current_currency']= array(
28
  'code' => self::$multi_currency->get_client_currency(),
inc/currencies/class-wcml-multi-currency-shipping.php CHANGED
@@ -107,12 +107,8 @@ class WCML_Multi_Currency_Shipping{
107
  foreach( $packages as $package_id => $package ){
108
  if( isset( $package['rates'] ) ){
109
  foreach( $package['rates'] as $rate_id => $rate ){
110
- foreach( $rate->taxes as $tax_id => $tax){
111
-
112
- $packages[$package_id]['rates'][$rate_id]->taxes[$tax_id] =
113
- $this->multi_currency->prices->raw_price_filter( $tax );
114
-
115
- }
116
  }
117
  }
118
  }
107
  foreach( $packages as $package_id => $package ){
108
  if( isset( $package['rates'] ) ){
109
  foreach( $package['rates'] as $rate_id => $rate ){
110
+ $packages[$package_id]['rates'][$rate_id]->taxes =
111
+ WC_Tax::calc_shipping_tax( $packages[$package_id]['rates'][$rate_id]->cost, WC_Tax::get_shipping_tax_rates() );
 
 
 
 
112
  }
113
  }
114
  }
inc/currencies/class-wcml-multi-currency.php CHANGED
@@ -75,6 +75,11 @@ class WCML_Multi_Currency{
75
  */
76
  public $exchange_rate_services;
77
 
 
 
 
 
 
78
 
79
  /**
80
  * WCML_Multi_Currency constructor.
@@ -88,14 +93,15 @@ class WCML_Multi_Currency{
88
 
89
  $this->init_currencies();
90
 
 
91
  $this->prices = new WCML_Multi_Currency_Prices( $this );
92
 
93
- if( $this->_load_filters()) {
94
  $this->coupons = new WCML_Multi_Currency_Coupons();
95
  $this->shipping = new WCML_Multi_Currency_Shipping( $this );
96
  }
97
  $this->reports = new WCML_Multi_Currency_Reports();
98
- $this->orders = new WCML_Multi_Currency_Orders( $this );
99
  $this->admin_currency_selector = new WCML_Admin_Currency_Selector();
100
  $this->custom_prices = new WCML_Custom_Prices( $woocommerce_wpml );
101
  $this->currency_switcher = new WCML_Currency_Switcher( $woocommerce_wpml, $sitepress );
@@ -462,12 +468,6 @@ class WCML_Multi_Currency{
462
 
463
  public function switch_currency(){
464
 
465
- $nonce = filter_input( INPUT_POST, 'wcml_nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
466
- if(!$nonce || !wp_verify_nonce($nonce, 'switch_currency')){
467
- echo json_encode(array('error' => __('Invalid nonce', 'woocommerce-multilingual')));
468
- die();
469
- }
470
-
471
  $currency = filter_input( INPUT_POST, 'currency', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
472
  $force_switch = filter_input( INPUT_POST, 'force_switch', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
473
 
75
  */
76
  public $exchange_rate_services;
77
 
78
+ /**
79
+ * @var bool
80
+ */
81
+ public $load_filters;
82
+
83
 
84
  /**
85
  * WCML_Multi_Currency constructor.
93
 
94
  $this->init_currencies();
95
 
96
+ $this->load_filters = $this->_load_filters();
97
  $this->prices = new WCML_Multi_Currency_Prices( $this );
98
 
99
+ if( $this->load_filters ) {
100
  $this->coupons = new WCML_Multi_Currency_Coupons();
101
  $this->shipping = new WCML_Multi_Currency_Shipping( $this );
102
  }
103
  $this->reports = new WCML_Multi_Currency_Reports();
104
+ $this->orders = new WCML_Multi_Currency_Orders( $this, $woocommerce_wpml );
105
  $this->admin_currency_selector = new WCML_Admin_Currency_Selector();
106
  $this->custom_prices = new WCML_Custom_Prices( $woocommerce_wpml );
107
  $this->currency_switcher = new WCML_Currency_Switcher( $woocommerce_wpml, $sitepress );
468
 
469
  public function switch_currency(){
470
 
 
 
 
 
 
 
471
  $currency = filter_input( INPUT_POST, 'currency', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
472
  $force_switch = filter_input( INPUT_POST, 'force_switch', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
473
 
inc/currencies/currency-switcher/class-wcml-currency-switcher-ajax.php CHANGED
@@ -188,7 +188,8 @@ class WCML_Currency_Switcher_Ajax{
188
  'switcher_id' => $_POST['switcher_id'],
189
  'format' => isset( $_POST['template'] ) ? stripslashes_deep( $_POST['template'] ) : '%name% (%symbol%) - %code%',
190
  'switcher_style' => $_POST['switcher_style'],
191
- 'color_scheme' => $_POST['color_scheme']
 
192
  )
193
  );
194
  $switcher_preview = ob_get_contents();
188
  'switcher_id' => $_POST['switcher_id'],
189
  'format' => isset( $_POST['template'] ) ? stripslashes_deep( $_POST['template'] ) : '%name% (%symbol%) - %code%',
190
  'switcher_style' => $_POST['switcher_style'],
191
+ 'color_scheme' => $_POST['color_scheme'],
192
+ 'preview' => true
193
  )
194
  );
195
  $switcher_preview = ob_get_contents();
inc/currencies/currency-switcher/class-wcml-currency-switcher-templates.php CHANGED
@@ -113,7 +113,7 @@ class WCML_Currency_Switcher_Templates {
113
  */
114
  private function get_uploads_path() {
115
  if ( ! $this->uploads_path ) {
116
- $uploads = wp_get_upload_dir();
117
 
118
  if ( isset( $uploads['basedir'] ) ) {
119
  $this->uploads_path = $uploads['basedir'];
@@ -417,4 +417,26 @@ class WCML_Currency_Switcher_Templates {
417
  public function set_templates( $templates ) {
418
  $this->templates = $templates;
419
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
420
  }
113
  */
114
  private function get_uploads_path() {
115
  if ( ! $this->uploads_path ) {
116
+ $uploads = wp_upload_dir( null, false );
117
 
118
  if ( isset( $uploads['basedir'] ) ) {
119
  $this->uploads_path = $uploads['basedir'];
417
  public function set_templates( $templates ) {
418
  $this->templates = $templates;
419
  }
420
+
421
+ public function check_is_active( $template ){
422
+ $is_active = false;
423
+
424
+ $active_templates = $this->get_active_templates();
425
+
426
+ foreach( $active_templates as $template_key => $active_template ){
427
+ if ( $template === $template_key ){
428
+ $is_active = true;
429
+ break;
430
+ }
431
+ }
432
+
433
+ return $is_active;
434
+
435
+ }
436
+
437
+ public function get_first_active( ){
438
+
439
+ return current( array_keys( $this->get_active_templates() ) );
440
+
441
+ }
442
  }
inc/currencies/currency-switcher/class-wcml-currency-switcher.php CHANGED
@@ -54,10 +54,15 @@ class WCML_Currency_Switcher{
54
  }
55
 
56
  public function wcml_currency_switcher( $args = array() ) {
 
57
  if ( is_page( wc_get_page_id( 'myaccount' ) ) ) {
58
  return '';
59
  }
60
 
 
 
 
 
61
  if( !isset( $args[ 'switcher_id' ] ) ){
62
  $args[ 'switcher_id' ] = 'product';
63
  }
@@ -70,8 +75,14 @@ class WCML_Currency_Switcher{
70
  $currency_switcher_settings = $wcml_settings[ 'currency_switchers' ][ $args[ 'switcher_id' ] ];
71
  }
72
 
73
- if ( !isset( $args[ 'switcher_style' ] ) ) {
74
- $args[ 'switcher_style' ] = isset( $currency_switcher_settings[ 'switcher_style' ] ) ? $currency_switcher_settings[ 'switcher_style' ] : 'wcml-dropdown';
 
 
 
 
 
 
75
  }
76
 
77
  if ( !isset( $args[ 'format' ] ) ) {
@@ -94,9 +105,9 @@ class WCML_Currency_Switcher{
94
  $show_currency_switcher = false;
95
  }elseif( is_product() ){
96
  $current_product_id = get_post()->ID;
97
- $original_product_language = $this->woocommerce_wpml->products->get_original_product_language( $current_product_id );
98
  $use_custom_prices = get_post_meta(
99
- apply_filters( 'translate_object_id', $current_product_id, get_post_type( $current_product_id ), true, $original_product_language ),
100
  '_wcml_custom_prices_status',
101
  true
102
  );
@@ -195,6 +206,7 @@ class WCML_Currency_Switcher{
195
  * @deprecated 3.9
196
  */
197
  public function currency_switcher( $args = array() ){
 
198
  $this->wcml_currency_switcher( $args );
199
  }
200
 
@@ -271,4 +283,26 @@ class WCML_Currency_Switcher{
271
  );
272
  }
273
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
274
  }
54
  }
55
 
56
  public function wcml_currency_switcher( $args = array() ) {
57
+
58
  if ( is_page( wc_get_page_id( 'myaccount' ) ) ) {
59
  return '';
60
  }
61
 
62
+ if( !is_array( $args ) ){
63
+ $args = array();
64
+ }
65
+
66
  if( !isset( $args[ 'switcher_id' ] ) ){
67
  $args[ 'switcher_id' ] = 'product';
68
  }
75
  $currency_switcher_settings = $wcml_settings[ 'currency_switchers' ][ $args[ 'switcher_id' ] ];
76
  }
77
 
78
+ $args = $this->check_and_convert_switcher_style( $args );
79
+
80
+ $switcher_style_not_available = !isset( $args[ 'switcher_style' ] ) || !$this->woocommerce_wpml->cs_templates->check_is_active( $args[ 'switcher_style' ] );
81
+ if (
82
+ !isset( $args[ 'preview' ] ) &&
83
+ $switcher_style_not_available
84
+ ) {
85
+ $args[ 'switcher_style' ] = isset( $currency_switcher_settings[ 'switcher_style' ] ) ? $currency_switcher_settings[ 'switcher_style' ] : $this->woocommerce_wpml->cs_templates->get_first_active();
86
  }
87
 
88
  if ( !isset( $args[ 'format' ] ) ) {
105
  $show_currency_switcher = false;
106
  }elseif( is_product() ){
107
  $current_product_id = get_post()->ID;
108
+ $original_product_id = $this->woocommerce_wpml->products->get_original_product_id( $current_product_id );
109
  $use_custom_prices = get_post_meta(
110
+ $original_product_id,
111
  '_wcml_custom_prices_status',
112
  true
113
  );
206
  * @deprecated 3.9
207
  */
208
  public function currency_switcher( $args = array() ){
209
+
210
  $this->wcml_currency_switcher( $args );
211
  }
212
 
283
  );
284
  }
285
 
286
+ //backward compatibility to convert switcher style for users who uses old parameters wcml-1874
287
+ public function check_and_convert_switcher_style( $args ){
288
+
289
+ if( isset( $args[ 'switcher_style' ] ) ){
290
+ if(
291
+ 'list' === $args[ 'switcher_style' ] &&
292
+ isset( $args[ 'orientation' ] )
293
+ ){
294
+ if( 'horizontal' === $args[ 'orientation' ] ){
295
+ $args[ 'switcher_style' ] = 'wcml-horizontal-list';
296
+ }else{
297
+ $args[ 'switcher_style' ] = 'wcml-vertical-list';
298
+ }
299
+ unset( $args[ 'orientation' ] );
300
+ }elseif( 'dropdown' === $args[ 'switcher_style' ] ){
301
+ $args[ 'switcher_style' ] = 'wcml-dropdown';
302
+ }
303
+ }
304
+
305
+ return $args;
306
+ }
307
+
308
  }
inc/rest-api-support/class-wcml-rest-api-support-v1.php ADDED
@@ -0,0 +1,397 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WCML_REST_API_Support_V1{
4
+
5
+ /** @var woocommerce_wpml */
6
+ private $woocommerce_wpml;
7
+ /** @var Sitepress */
8
+ private $sitepress;
9
+
10
+ function __construct( &$woocommerce_wpml, &$sitepress ) {
11
+ $this->woocommerce_wpml =& $woocommerce_wpml;
12
+ $this->sitepress =& $sitepress;
13
+ }
14
+
15
+ /**
16
+ * Adding hooks
17
+ */
18
+ public function initialize(){
19
+
20
+ $this->prevent_default_lang_url_redirect();
21
+
22
+ add_action( 'rest_api_init', array( $this, 'set_language_for_request' ) );
23
+
24
+ add_action( 'parse_query', array($this, 'auto_adjust_included_ids') );
25
+
26
+ // Products
27
+ add_action( 'woocommerce_rest_prepare_product', array( $this, 'append_product_language_and_translations' ) );
28
+ add_action( 'woocommerce_rest_prepare_product', array( $this, 'append_product_secondary_prices' ) );
29
+
30
+ add_filter( 'woocommerce_rest_product_query', array( $this, 'filter_products_query' ), 10, 2 );
31
+
32
+ add_action( 'woocommerce_rest_insert_product', array( $this, 'set_product_language' ), 10, 2 );
33
+ add_action( 'woocommerce_rest_update_product', array( $this, 'set_product_language' ), 10, 2 );
34
+
35
+ add_action( 'woocommerce_rest_insert_product', array( $this, 'set_product_custom_prices' ), 10, 2 );
36
+ add_action( 'woocommerce_rest_update_product', array( $this, 'set_product_custom_prices' ), 10, 2 );
37
+
38
+ add_action( 'woocommerce_rest_prepare_product', array( $this, 'copy_product_custom_fields' ), 10 , 3 );
39
+
40
+ // Orders
41
+ add_filter( 'woocommerce_rest_shop_order_query', array( $this, 'filter_orders_by_language' ), 20, 2 );
42
+ add_action( 'woocommerce_rest_prepare_shop_order', array( $this, 'filter_order_items_by_language'), 10, 3 );
43
+ add_action( 'woocommerce_rest_insert_shop_order' , array( $this, 'set_order_language' ), 10, 2 );
44
+
45
+ // Terms
46
+ add_action( 'woocommerce_rest_product_cat_query', array($this, 'filter_terms_query' ), 10, 2 );
47
+ add_action( 'woocommerce_rest_product_tag_query', array($this, 'filter_terms_query' ), 10, 2 );
48
+
49
+ }
50
+
51
+ /**
52
+ * @param WP_REST_Server $wp_rest_server
53
+ * enforces the language of request as the current language to be able to filter items by language
54
+ */
55
+ public function set_language_for_request( $wp_rest_server ){
56
+ if( isset( $_GET['lang'] ) ){
57
+ $request_language = $_GET['lang'];
58
+ $active_languages = $this->sitepress->get_active_languages();
59
+ if( isset( $active_languages[ $request_language ] ) ){
60
+ $this->sitepress->switch_lang( $request_language );
61
+ }
62
+ }
63
+ }
64
+
65
+ /**
66
+ * Prevent WPML redirection when using the default language as a parameter in the url
67
+ */
68
+ private function prevent_default_lang_url_redirect(){
69
+ $exp = explode( '?', $_SERVER['REQUEST_URI'] );
70
+ if ( ! empty( $exp[1] ) ) {
71
+ parse_str( $exp[1], $vars );
72
+ if ( isset($vars['lang']) && $vars['lang'] === $this->sitepress->get_default_language() ) {
73
+ unset( $vars['lang'] );
74
+ $_SERVER['REQUEST_URI'] = $exp[0] . '?' . http_build_query( $vars );
75
+ }
76
+ }
77
+ }
78
+
79
+ // Use url without the language parameter. Needed for the signature match.
80
+ public static function remove_wpml_global_url_filters(){
81
+ global $wpml_url_filters;
82
+ remove_filter( 'home_url', array( $wpml_url_filters, 'home_url_filter' ), - 10 );
83
+ }
84
+
85
+ /**
86
+ * When lang=all don't filter products by language
87
+ *
88
+ * @param array $args
89
+ * @param WP_REST_Request $request
90
+ *
91
+ * @return array
92
+ */
93
+ public function filter_products_query( $args, $request ){
94
+ $data = $request->get_params();
95
+ if( isset( $data['lang'] ) && $data['lang'] === 'all' ){
96
+ global $wpml_query_filter;
97
+ remove_filter( 'posts_join', array( $wpml_query_filter, 'posts_join_filter' ), 10 );
98
+ remove_filter( 'posts_where', array( $wpml_query_filter, 'posts_where_filter' ), 10 );
99
+ }
100
+ return $args;
101
+ }
102
+
103
+ /**
104
+ * When lang=all don't filter terms by language
105
+ *
106
+ * @param array $args
107
+ * @param WP_REST_Request $request
108
+ *
109
+ * @return array
110
+ */
111
+ public function filter_terms_query( $args, $request ){
112
+ $data = $request->get_params();
113
+ if( isset( $data['lang'] ) && $data['lang'] === 'all' ){
114
+ remove_filter( 'terms_clauses', array( $this->sitepress, 'terms_clauses' ), 10, 4 );
115
+ remove_filter( 'get_term', array( $this->sitepress, 'get_term_adjust_id' ), 1, 1 );
116
+ }
117
+ return $args;
118
+ }
119
+
120
+ /**
121
+ * @param WP_Query $wp_query
122
+ */
123
+ public function auto_adjust_included_ids( $wp_query ){
124
+ $lang = $wp_query->get('lang');
125
+ $include = $wp_query->get('post__in');
126
+ if( empty( $lang ) && !empty( $include ) ){
127
+ $filtered_include = array();
128
+ foreach( $include as $id ){
129
+ $filtered_include[] = apply_filters( 'translate_object_id', $id, get_post_type($id), true );
130
+ }
131
+ $wp_query->set( 'post__in' , $filtered_include );
132
+ }
133
+ }
134
+
135
+ /**
136
+ * Appends the language and translation information to the get_product response
137
+ *
138
+ * @param $product_data
139
+ *
140
+ * @return WP_REST_Response
141
+ */
142
+ public function append_product_language_and_translations( $product_data ){
143
+
144
+ $product_data->data['translations'] = array();
145
+
146
+ $trid = $this->sitepress->get_element_trid( $product_data->data['id'], 'post_product' );
147
+
148
+ if( $trid ) {
149
+ $translations = $this->sitepress->get_element_translations( $trid, 'post_product' );
150
+ foreach ( $translations as $translation ) {
151
+ if ( $translation->element_id == $product_data->data['id'] ) {
152
+ $product_language = $translation->language_code;
153
+ } else {
154
+ $product_data->data['translations'][ $translation->language_code ] = $translation->element_id;
155
+ }
156
+ }
157
+
158
+ $product_data->data['lang'] = $product_language;
159
+ }
160
+
161
+ return $product_data;
162
+ }
163
+
164
+ /**
165
+ * Appends the secondary prices information to the get_product response
166
+ *
167
+ * @param $product_data
168
+ *
169
+ * @return WP_REST_Response
170
+ */
171
+ public function append_product_secondary_prices( $product_data ){
172
+
173
+ if( !empty($this->woocommerce_wpml->multi_currency) && !empty($this->woocommerce_wpml->settings['currencies_order']) ){
174
+
175
+ $product_data->data['multi-currency-prices'] = array();
176
+
177
+ $custom_prices_on = get_post_meta( $product_data->data['id'], '_wcml_custom_prices_status', true);
178
+
179
+ foreach( $this->woocommerce_wpml->settings['currencies_order'] as $currency ){
180
+
181
+ if( $currency != get_option('woocommerce_currency') ){
182
+
183
+ if( $custom_prices_on ){
184
+
185
+ $custom_prices = (array) $this->woocommerce_wpml->multi_currency->custom_prices->get_product_custom_prices( $product_data->data['id'], $currency );
186
+ foreach( $custom_prices as $key => $price){
187
+ $product_data->data['multi-currency-prices'][$currency][ preg_replace('#^_#', '', $key) ] = $price;
188
+
189
+ }
190
+
191
+ } else {
192
+ $product_data->data['multi-currency-prices'][$currency]['regular_price'] =
193
+ $this->woocommerce_wpml->multi_currency->prices->raw_price_filter( $product_data->data['regular_price'], $currency );
194
+ if( !empty($product_data->data['sale_price']) ){
195
+ $product_data->data['multi-currency-prices'][$currency]['sale_price'] =
196
+ $this->woocommerce_wpml->multi_currency->prices->raw_price_filter( $product_data->data['sale_price'], $currency );
197
+ }
198
+ }
199
+
200
+ }
201
+
202
+ }
203
+
204
+ }
205
+
206
+ return $product_data;
207
+ }
208
+
209
+ /**
210
+ * Sets the product information according to the provided language
211
+ *
212
+ * @param WP_Post $post
213
+ * @param WP_REST_Request $request
214
+ *
215
+ * @throws WC_REST_Exception
216
+ *
217
+ */
218
+ public function set_product_language( $post, $request ){
219
+
220
+ $data = $request->get_params();
221
+
222
+ if( isset( $data['lang'] )){
223
+ $active_languages = $this->sitepress->get_active_languages();
224
+ if( !isset( $active_languages[$data['lang']] ) ){
225
+ throw new WC_REST_Exception( '404', sprintf( __( 'Invalid language parameter: %s', 'woocommerce-multilingual' ), $data['lang'] ), '404' );
226
+ }
227
+ if( isset( $data['translation_of'] ) ){
228
+ $trid = $this->sitepress->get_element_trid( $data['translation_of'], 'post_product' );
229
+ if( empty($trid) ){
230
+ throw new WC_REST_Exception( '404', sprintf( __( 'Source product id not found: %s', 'woocommerce-multilingual' ), $data['translation_of'] ), '404' );
231
+ }
232
+ }else{
233
+ $trid = null;
234
+ }
235
+
236
+ $this->sitepress->set_element_language_details( $post->ID, 'post_product', $trid, $data['lang'] );
237
+ wpml_tm_save_post( $post->ID, $post , ICL_TM_COMPLETE );
238
+ }else{
239
+ if( isset( $data['translation_of'] ) ){
240
+ throw new WC_REST_Exception( '404', __( 'Using "translation_of" requires providing a "lang" parameter too', 'woocommerce-multilingual' ), '404' );
241
+ }
242
+ }
243
+
244
+ }
245
+
246
+ /**
247
+ * Sets custom prices in secondary currencies for products
248
+ *
249
+ * @param WP_Post $post
250
+ * @param WP_REST_Request $request
251
+ *
252
+ * @throws WC_API_Exception
253
+ *
254
+ */
255
+ public function set_product_custom_prices( $post, $request ){
256
+
257
+ $data = $request->get_params();
258
+
259
+ if( !empty( $this->woocommerce_wpml->multi_currency ) ){
260
+
261
+ if( !empty( $data['custom_prices'] ) ){
262
+
263
+ $original_post_id = $this->sitepress->get_original_element_id_filter('', $post->ID, 'post_product' );
264
+
265
+ update_post_meta( $original_post_id, '_wcml_custom_prices_status', 1);
266
+
267
+ foreach( $data['custom_prices'] as $currency => $prices ){
268
+
269
+ $prices_uscore = array();
270
+ foreach( $prices as $k => $p){
271
+ $prices_uscore['_' . $k] = $p;
272
+ }
273
+ $this->woocommerce_wpml->multi_currency->custom_prices->update_custom_prices( $original_post_id, $prices_uscore, $currency );
274
+
275
+ }
276
+
277
+ }
278
+ }
279
+
280
+ }
281
+
282
+ /**
283
+ * @param WP_REST_Response $response
284
+ * @param mixed $object
285
+ * @param WP_REST_Request $request
286
+ *
287
+ * Copy custom fields explicitly
288
+ *
289
+ * @return WP_REST_Response
290
+ */
291
+ public function copy_product_custom_fields($response, $object, $request){
292
+ global $wpdb;
293
+ global $wpml_post_translations;
294
+
295
+ $data = $request->get_params();
296
+
297
+ if( isset( $data['id'] ) ){
298
+ $translations = $wpml_post_translations->get_element_translations ( $data['id'], false, true );
299
+ foreach ( $translations as $translation_id ) {
300
+ $this->sitepress->copy_custom_fields ( $data['id'], $translation_id );
301
+ }
302
+ }
303
+
304
+ return $response;
305
+ }
306
+
307
+ public function filter_orders_by_language( $args, $request ){
308
+
309
+ $lang = $request->get_param( 'lang' );
310
+
311
+ if( !is_null( $lang ) && $lang !== 'all' ){
312
+
313
+ $args['meta_query'][] = array(
314
+ 'key' => 'wpml_language',
315
+ 'value' => strval( $lang )
316
+ );
317
+
318
+ }
319
+
320
+ return $args;
321
+ }
322
+
323
+ /**
324
+ * Filters the items of an order according to a given languages
325
+ *
326
+ * @param WP_REST_Response $response
327
+ * @param WC_Order $order
328
+ * @param WP_REST_Request $request
329
+ * @return WP_REST_Response
330
+ */
331
+
332
+ public function filter_order_items_by_language( $response, $order, $request ){
333
+
334
+ $lang = get_query_var('lang');
335
+
336
+ $order_lang = get_post_meta( $order->ID, 'wpml_language', true );
337
+
338
+ if( $order_lang != $lang ){
339
+
340
+ foreach( $response->data['line_items'] as $k => $item ){
341
+
342
+ global $wpdb;
343
+ $sql = "SELECT meta_value FROM {$wpdb->prefix}woocommerce_order_itemmeta WHERE order_item_id=%d AND meta_key='_product_id'";
344
+ $product_id = $wpdb->get_var( $wpdb->prepare( $sql, $item['id']) );
345
+
346
+ if( $product_id ){
347
+
348
+ $translated_product_id = apply_filters( 'translate_object_id', $product_id, 'product', true, $lang );
349
+
350
+ if( $translated_product_id ){
351
+ $translated_product = get_post( $translated_product_id );
352
+ $response->data['line_items'][$k]['product_id'] = $translated_product_id;
353
+ if( $translated_product->post_type == 'product_variation' ){
354
+ $post_parent = get_post( $translated_product->post_parent );
355
+ $post_name = $post_parent->post_title;
356
+ } else {
357
+ $post_name = $translated_product->post_title;
358
+ }
359
+ $response->data['line_items'][$k]['name'] = $post_name;
360
+ }
361
+
362
+ }
363
+
364
+ }
365
+
366
+ }
367
+
368
+ return $response;
369
+ }
370
+
371
+ /**
372
+ * Sets the language for a new order
373
+ *
374
+ * @param WP_Post $post
375
+ * @param WP_REST_Request $request
376
+ *
377
+ * @throws WC_REST_Exception
378
+ */
379
+ public function set_order_language( $post, $request ){
380
+
381
+ $data = $request->get_params();
382
+ if( isset( $data['lang'] ) ){
383
+ $order_id = $post->ID;
384
+ $active_languages = $this->sitepress->get_active_languages();
385
+ if( !isset( $active_languages[$data['lang']] ) ){
386
+ throw new WC_REST_Exception( '404', sprintf( __( 'Invalid language parameter: %s' ), $data['lang'] ), '404' );
387
+ }
388
+
389
+ update_post_meta( $order_id, 'wpml_language', $data['lang'] );
390
+
391
+ }
392
+
393
+ }
394
+
395
+
396
+
397
+ }
inc/rest-api-support/class-wcml-rest-api-support.php ADDED
@@ -0,0 +1,439 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WCML_REST_API_Support{
4
+
5
+ /** @var woocommerce_wpml */
6
+ private $woocommerce_wpml;
7
+ /** @var Sitepress */
8
+ private $sitepress;
9
+
10
+ function __construct( &$woocommerce_wpml, &$sitepress ) {
11
+ $this->woocommerce_wpml =& $woocommerce_wpml;
12
+ $this->sitepress =& $sitepress;
13
+ }
14
+
15
+ /**
16
+ * Adding hooks
17
+ */
18
+ public function initialize(){
19
+
20
+ $this->prevent_default_lang_url_redirect();
21
+
22
+ add_action( 'rest_api_init', array( $this, 'set_language_for_request' ) );
23
+
24
+ add_action( 'parse_query', array($this, 'auto_adjust_included_ids') );
25
+
26
+ // Products
27
+ add_action( 'woocommerce_rest_prepare_product_object', array( $this, 'append_product_language_and_translations' ) );
28
+ add_action( 'woocommerce_rest_prepare_product_object', array( $this, 'append_product_secondary_prices' ) );
29
+ add_filter( 'woocommerce_rest_product_query', array( $this, 'filter_products_query' ), 10, 2 );
30
+ add_action( 'woocommerce_rest_insert_product_object', array( $this, 'set_product_language' ), 10, 2 );
31
+ add_action( 'woocommerce_rest_insert_product_object', array( $this, 'set_product_custom_prices' ), 10, 2 );
32
+ add_action( 'woocommerce_rest_prepare_product_object', array( $this, 'copy_product_custom_fields' ), 10 , 3 );
33
+
34
+ // Orders
35
+ add_filter( 'woocommerce_rest_shop_order_object_query', array( $this, 'filter_orders_by_language' ), 20, 2 );
36
+ add_action( 'woocommerce_rest_prepare_shop_order_object', array( $this, 'filter_order_items_by_language'), 10, 3 );
37
+ add_action( 'woocommerce_rest_insert_shop_order_object' , array( $this, 'set_order_language' ), 10, 2 );
38
+
39
+ // Terms
40
+ add_action( 'woocommerce_rest_product_cat_query', array($this, 'filter_terms_query' ), 10, 2 );
41
+ add_action( 'woocommerce_rest_product_tag_query', array($this, 'filter_terms_query' ), 10, 2 );
42
+
43
+ }
44
+
45
+ /**
46
+ * Check if is request to the WooCommerce REST API.
47
+ *
48
+ * @return bool
49
+ */
50
+ public static function is_rest_api_request(){
51
+
52
+ if ( empty( $_SERVER['REQUEST_URI'] ) ) {
53
+ return false;
54
+ }
55
+
56
+ $rest_prefix = trailingslashit( rest_get_url_prefix() );
57
+ // Check if WooCommerce endpoint.
58
+ $woocommerce = ( false !== strpos( $_SERVER['REQUEST_URI'], $rest_prefix . 'wc/' ) );
59
+
60
+ return apply_filters( 'woocommerce_rest_is_request_to_rest_api', $woocommerce );
61
+
62
+ }
63
+
64
+ /**
65
+ * @return int
66
+ * Returns the version number of the API used for the current request
67
+ */
68
+ public static function get_api_request_version(){
69
+ $version = 0;
70
+ $rest_prefix = trailingslashit( rest_get_url_prefix() );
71
+ if( preg_match( "@" . $rest_prefix . "wc/v([0-9]+)/@", $_SERVER['REQUEST_URI'], $matches ) ){
72
+ $version = intval($matches[1]);
73
+ }
74
+ return $version;
75
+ }
76
+
77
+ /**
78
+ * @param WP_REST_Server $wp_rest_server
79
+ * enforces the language of request as the current language to be able to filter items by language
80
+ */
81
+ public function set_language_for_request( $wp_rest_server ){
82
+ if( isset( $_GET['lang'] ) ){
83
+ $request_language = $_GET['lang'];
84
+ $active_languages = $this->sitepress->get_active_languages();
85
+ if( isset( $active_languages[ $request_language ] ) ){
86
+ $this->sitepress->switch_lang( $request_language );
87
+ }
88
+ }
89
+ }
90
+
91
+ /**
92
+ * Prevent WPML redirection when using the default language as a parameter in the url
93
+ */
94
+ private function prevent_default_lang_url_redirect(){
95
+ $exp = explode( '?', $_SERVER['REQUEST_URI'] );
96
+ if ( ! empty( $exp[1] ) ) {
97
+ parse_str( $exp[1], $vars );
98
+ if ( isset($vars['lang']) && $vars['lang'] === $this->sitepress->get_default_language() ) {
99
+ unset( $vars['lang'] );
100
+ $_SERVER['REQUEST_URI'] = $exp[0] . '?' . http_build_query( $vars );
101
+ }
102
+ }
103
+ }
104
+
105
+ // Use url without the language parameter. Needed for the signature match.
106
+ public static function remove_wpml_global_url_filters(){
107
+ global $wpml_url_filters;
108
+ remove_filter( 'home_url', array( $wpml_url_filters, 'home_url_filter' ), - 10 );
109
+ }
110
+
111
+ /**
112
+ * When lang=all don't filter products by language
113
+ *
114
+ * @param array $args
115
+ * @param WP_REST_Request $request
116
+ *
117
+ * @return array
118
+ */
119
+ public function filter_products_query( $args, $request ){
120
+ $data = $request->get_params();
121
+ if( isset( $data['lang'] ) && $data['lang'] === 'all' ){
122
+ global $wpml_query_filter;
123
+ remove_filter( 'posts_join', array( $wpml_query_filter, 'posts_join_filter' ), 10 );
124
+ remove_filter( 'posts_where', array( $wpml_query_filter, 'posts_where_filter' ), 10 );
125
+ }
126
+ return $args;
127
+ }
128
+
129
+ /**
130
+ * When lang=all don't filter terms by language
131
+ *
132
+ * @param array $args
133
+ * @param WP_REST_Request $request
134
+ *
135
+ * @return array
136
+ * @throws WC_REST_Exception
137
+ */
138
+ public function filter_terms_query( $args, $request ) {
139
+
140
+ $data = $request->get_params();
141
+
142
+ if ( isset( $data['lang'] ) ) {
143
+
144
+ $active_languages = $this->sitepress->get_active_languages();
145
+
146
+ if ( $data['lang'] === 'all' ) {
147
+ remove_filter( 'terms_clauses', array( $this->sitepress, 'terms_clauses' ), 10, 4 );
148
+ remove_filter( 'get_term', array( $this->sitepress, 'get_term_adjust_id' ), 1, 1 );
149
+ } elseif ( ! isset( $active_languages[ $data['lang'] ] ) ) {
150
+ throw new WC_REST_Exception(
151
+ '404',
152
+ sprintf( __( 'Invalid language parameter: %s', 'woocommerce-multilingual' ),
153
+ $data['lang'] ),
154
+ '404'
155
+ );
156
+ }
157
+
158
+ }
159
+
160
+ return $args;
161
+ }
162
+
163
+ /**
164
+ * @param WP_Query $wp_query
165
+ */
166
+ public function auto_adjust_included_ids( $wp_query ){
167
+ $lang = $wp_query->get('lang');
168
+ $include = $wp_query->get('post__in');
169
+ if( empty( $lang ) && !empty( $include ) ){
170
+ $filtered_include = array();
171
+ foreach( $include as $id ){
172
+ $filtered_include[] = apply_filters( 'translate_object_id', $id, get_post_type($id), true );
173
+ }
174
+ $wp_query->set( 'post__in' , $filtered_include );
175
+ }
176
+ }
177
+
178
+ /**
179
+ * Appends the language and translation information to the get_product response
180
+ *
181
+ * @param $product_data
182
+ *
183
+ * @return WP_REST_Response
184
+ */
185
+ public function append_product_language_and_translations( $product_data ){
186
+
187
+ $product_data->data['translations'] = array();
188
+
189
+ $trid = $this->sitepress->get_element_trid( $product_data->data['id'], 'post_product' );
190
+
191
+ if( $trid ) {
192
+ $translations = $this->sitepress->get_element_translations( $trid, 'post_product' );
193
+ foreach ( $translations as $translation ) {
194
+ if ( $translation->element_id == $product_data->data['id'] ) {
195
+ $product_language = $translation->language_code;
196
+ } else {
197
+ $product_data->data['translations'][ $translation->language_code ] = $translation->element_id;
198
+ }
199
+ }
200
+
201
+ $product_data->data['lang'] = $product_language;
202
+ }
203
+
204
+ return $product_data;
205
+ }
206
+
207
+ /**
208
+ * Appends the secondary prices information to the get_product response
209
+ *
210
+ * @param $product_data
211
+ *
212
+ * @return WP_REST_Response
213
+ */
214
+ public function append_product_secondary_prices( $product_data ){
215
+
216
+ if( !empty($this->woocommerce_wpml->multi_currency) && !empty($this->woocommerce_wpml->settings['currencies_order']) ){
217
+
218
+ $product_data->data['multi-currency-prices'] = array();
219
+
220
+ $custom_prices_on = get_post_meta( $product_data->data['id'], '_wcml_custom_prices_status', true);
221
+
222
+ foreach( $this->woocommerce_wpml->settings['currencies_order'] as $currency ){
223
+
224
+ if( $currency != get_option('woocommerce_currency') ){
225
+
226
+ if( $custom_prices_on ){
227
+
228
+ $custom_prices = (array) $this->woocommerce_wpml->multi_currency->custom_prices->get_product_custom_prices( $product_data->data['id'], $currency );
229
+ foreach( $custom_prices as $key => $price){
230
+ $product_data->data['multi-currency-prices'][$currency][ preg_replace('#^_#', '', $key) ] = $price;
231
+
232
+ }
233
+
234
+ } else {
235
+ $product_data->data['multi-currency-prices'][$currency]['regular_price'] =
236
+ $this->woocommerce_wpml->multi_currency->prices->raw_price_filter( $product_data->data['regular_price'], $currency );
237
+ if( !empty($product_data->data['sale_price']) ){
238
+ $product_data->data['multi-currency-prices'][$currency]['sale_price'] =
239
+ $this->woocommerce_wpml->multi_currency->prices->raw_price_filter( $product_data->data['sale_price'], $currency );
240
+ }
241
+ }
242
+
243
+ }
244
+
245
+ }
246
+
247
+ }
248
+
249
+ return $product_data;
250
+ }
251
+
252
+ /**
253
+ * Sets the product information according to the provided language
254
+ *
255
+ * @param object $product
256
+ * @param WP_REST_Request $request
257
+ *
258
+ * @throws WC_REST_Exception
259
+ *
260
+ */
261
+ public function set_product_language( $product, $request ){
262
+
263
+ $data = $request->get_params();
264
+
265
+ if( isset( $data['lang'] )){
266
+ $active_languages = $this->sitepress->get_active_languages();
267
+ if( !isset( $active_languages[$data['lang']] ) ){
268
+ throw new WC_REST_Exception( '404', sprintf( __( 'Invalid language parameter: %s', 'woocommerce-multilingual' ), $data['lang'] ), '404' );
269
+ }
270
+ if( isset( $data['translation_of'] ) ){
271
+ $trid = $this->sitepress->get_element_trid( $data['translation_of'], 'post_product' );
272
+ if( empty($trid) ){
273
+ throw new WC_REST_Exception( '404', sprintf( __( 'Source product id not found: %s', 'woocommerce-multilingual' ), $data['translation_of'] ), '404' );
274
+ }
275
+ }else{
276
+ $trid = null;
277
+ }
278
+
279
+ $this->sitepress->set_element_language_details( $product->get_id(), 'post_product', $trid, $data['lang'] );
280
+ wpml_tm_save_post( $product->get_id(), get_post( $product->get_id() ), ICL_TM_COMPLETE );
281
+ }else{
282
+ if( isset( $data['translation_of'] ) ){
283
+ throw new WC_REST_Exception( '404', __( 'Using "translation_of" requires providing a "lang" parameter too', 'woocommerce-multilingual' ), '404' );
284
+ }
285
+ }
286
+
287
+ }
288
+
289
+ /**
290
+ * Sets custom prices in secondary currencies for products
291
+ *
292
+ * @param object $product
293
+ * @param WP_REST_Request $request
294
+ *
295
+ * @throws WC_API_Exception
296
+ *
297
+ */
298
+ public function set_product_custom_prices( $product, $request ){
299
+
300
+ $data = $request->get_params();
301
+
302
+ if( !empty( $this->woocommerce_wpml->multi_currency ) ){
303
+
304
+ if( !empty( $data['custom_prices'] ) ){
305
+
306
+ $original_post_id = $this->sitepress->get_original_element_id_filter('', $product->get_id(), 'post_product' );
307
+
308
+ update_post_meta( $original_post_id, '_wcml_custom_prices_status', 1);
309
+
310
+ foreach( $data['custom_prices'] as $currency => $prices ){
311
+
312
+ $prices_uscore = array();
313
+ foreach( $prices as $k => $p){
314
+ $prices_uscore['_' . $k] = $p;
315
+ }
316
+ $this->woocommerce_wpml->multi_currency->custom_prices->update_custom_prices( $original_post_id, $prices_uscore, $currency );
317
+
318
+ }
319
+
320
+ }
321
+ }
322
+
323
+ }
324
+
325
+ /**
326
+ * @param WP_REST_Response $response
327
+ * @param mixed $object
328
+ * @param WP_REST_Request $request
329
+ *
330
+ * Copy custom fields explicitly
331
+ *
332
+ * @return WP_REST_Response
333
+ */
334
+ public function copy_product_custom_fields($response, $object, $request){
335
+ global $wpdb;
336
+ global $wpml_post_translations;
337
+
338
+ $data = $request->get_params();
339
+
340
+ if( isset( $data['id'] ) ) {
341
+ $translations = $wpml_post_translations->get_element_translations( $data['id'], false, true );
342
+ foreach ( $translations as $translation_id ) {
343
+ $this->sitepress->copy_custom_fields( $data['id'], $translation_id );
344
+ }
345
+ }
346
+
347
+ return $response;
348
+ }
349
+
350
+ public function filter_orders_by_language( $args, $request ){
351
+
352
+ $lang = $request->get_param( 'lang' );
353
+
354
+ if( !is_null( $lang ) && $lang !== 'all' ){
355
+
356
+ $args['meta_query'][] = array(
357
+ 'key' => 'wpml_language',
358
+ 'value' => strval( $lang )
359
+ );
360
+
361
+ }
362
+
363
+ return $args;
364
+ }
365
+
366
+ /**
367
+ * Filters the items of an order according to a given languages
368
+ *
369
+ * @param WP_REST_Response $response
370
+ * @param WC_Order $order
371
+ * @param WP_REST_Request $request
372
+ * @return WP_REST_Response
373
+ */
374
+
375
+ public function filter_order_items_by_language( $response, $order, $request ){
376
+
377
+ $lang = get_query_var('lang');
378
+ $order_lang = get_post_meta( $order->get_id(), 'wpml_language', true );
379
+
380
+ if( $order_lang != $lang || 1 ){
381
+
382
+ foreach( $response->data['line_items'] as $k => $item ){
383
+
384
+ global $wpdb;
385
+ $sql = "SELECT meta_value FROM {$wpdb->prefix}woocommerce_order_itemmeta WHERE order_item_id=%d AND meta_key='_product_id'";
386
+ $product_id = $wpdb->get_var( $wpdb->prepare( $sql, $item['id']) );
387
+
388
+ if( $product_id ){
389
+
390
+ $translated_product_id = apply_filters( 'translate_object_id', $product_id, 'product', true, $lang );
391
+
392
+ if( $translated_product_id ){
393
+ $translated_product = get_post( $translated_product_id );
394
+ $response->data['line_items'][$k]['product_id'] = $translated_product_id;
395
+ if( $translated_product->post_type == 'product_variation' ){
396
+ $post_parent = get_post( $translated_product->post_parent );
397
+ $post_name = $post_parent->post_title;
398
+ } else {
399
+ $post_name = $translated_product->post_title;
400
+ }
401
+ $response->data['line_items'][$k]['name'] = $post_name;
402
+ }
403
+
404
+ }
405
+
406
+ }
407
+
408
+ }
409
+
410
+ return $response;
411
+ }
412
+
413
+ /**
414
+ * Sets the language for a new order
415
+ *
416
+ * @param WC_Order $order
417
+ * @param WP_REST_Request $request
418
+ *
419
+ * @throws WC_REST_Exception
420
+ */
421
+ public function set_order_language( $order, $request ){
422
+
423
+ $data = $request->get_params();
424
+ if( isset( $data['lang'] ) ){
425
+ $order_id = $order->get_id();
426
+ $active_languages = $this->sitepress->get_active_languages();
427
+ if( !isset( $active_languages[$data['lang']] ) ){
428
+ throw new WC_REST_Exception( '404', sprintf( __( 'Invalid language parameter: %s' ), $data['lang'] ), '404' );
429
+ }
430
+
431
+ update_post_meta( $order_id, 'wpml_language', $data['lang'] );
432
+
433
+ }
434
+
435
+ }
436
+
437
+
438
+
439
+ }
inc/template-classes/class-wcml-menus-wrap.php CHANGED
@@ -156,7 +156,7 @@ class WCML_Menus_Wrap extends WPML_Templates_Factory {
156
  'rate' => array(
157
  'on' => !isset( $this->woocommerce_wpml->settings['rate-block'] ),
158
  'message' => sprintf(__('Thank you for using %sWooCommerce Multilingual%s! You can express your love and
159
- support by %s rating our plugin and saying that %sit works%s for you.', 'woocommerce_wpml'),
160
  '<strong>',
161
  '</strong>',
162
  '<a href="https://wordpress.org/support/view/plugin-reviews/woocommerce-multilingual?filter=5#postform" target="_blank">&#9733;&#9733;&#9733;&#9733;&#9733;</a>',
156
  'rate' => array(
157
  'on' => !isset( $this->woocommerce_wpml->settings['rate-block'] ),
158
  'message' => sprintf(__('Thank you for using %sWooCommerce Multilingual%s! You can express your love and
159
+ support by %s rating our plugin and saying that %sit works%s for you.', 'woocommerce-wpml'),
160
  '<strong>',
161
  '</strong>',
162
  '<a href="https://wordpress.org/support/view/plugin-reviews/woocommerce-multilingual?filter=5#postform" target="_blank">&#9733;&#9733;&#9733;&#9733;&#9733;</a>',
inc/template-classes/class-wcml-plugins-wrap.php CHANGED
@@ -28,8 +28,8 @@ class WCML_Plugins_Wrap {
28
  'media_version' => defined( 'WPML_MEDIA_VERSION' ),
29
  'tm_version' => defined( 'WPML_TM_VERSION' ),
30
  'st_version' => defined( 'WPML_ST_VERSION' ),
31
- 'wc' => class_exists('Woocommerce') ,
32
- 'old_wc' => class_exists('Woocommerce') && version_compare( WC_VERSION, '2.0', '<'),
33
  'wc_link' => 'http://wordpress.org/extend/plugins/woocommerce/',
34
  'strings' => array(
35
  'title' => __('WooCommerce Multilingual', 'woocommerce-multilingual'),
28
  'media_version' => defined( 'WPML_MEDIA_VERSION' ),
29
  'tm_version' => defined( 'WPML_TM_VERSION' ),
30
  'st_version' => defined( 'WPML_ST_VERSION' ),
31
+ 'wc' => class_exists('WooCommerce') ,
32
+ 'old_wc' => class_exists('WooCommerce') && version_compare( WC_VERSION, '2.0', '<'),
33
  'wc_link' => 'http://wordpress.org/extend/plugins/woocommerce/',
34
  'strings' => array(
35
  'title' => __('WooCommerce Multilingual', 'woocommerce-multilingual'),
inc/template-classes/class-wcml-products-ui.php CHANGED
@@ -120,16 +120,13 @@ class WCML_Products_UI extends WPML_Templates_Factory {
120
  }
121
 
122
  public function get_products_data(){
123
- global $iclTranslationManagement;
124
 
125
  $active_languages = $this->sitepress->get_active_languages();
126
 
127
  $products_info = $this->get_product_info_from_self_edit_mode();
128
-
129
  if( !$products_info ){
130
  $products_info = $this->get_product_info_for_translators();
131
  }
132
-
133
  if( !$products_info ){
134
  $products_info = $this->get_products_from_filter();
135
  }
@@ -210,11 +207,12 @@ class WCML_Products_UI extends WPML_Templates_Factory {
210
 
211
  if ( isset( $_GET[ 'prid' ] ) ) {
212
 
213
- if ( ! $this->woocommerce_wpml->products->is_original_product( $_GET[ 'prid' ] ) ) {
214
- $original_language = $this->woocommerce_wpml->products->get_original_product_language( $_GET[ 'prid' ] );
215
- $products[] = get_post( apply_filters( 'translate_object_id', $_GET[ 'prid' ], 'product', true, $original_language ) );
 
216
  } else {
217
- $products[] = get_post( $_GET[ 'prid' ] );
218
  }
219
  $products_count = 1;
220
 
@@ -390,6 +388,7 @@ class WCML_Products_UI extends WPML_Templates_Factory {
390
  $sql .= " LEFT JOIN {$wpdb->prefix}icl_translations AS t ON t.element_id = p.id";
391
 
392
  if(in_array($translation_status,array('not','need_update','in_progress','complete'))){
 
393
  foreach($this->sitepress->get_active_languages() as $lang){
394
 
395
  if( $lang['code'] == $slang ) continue;
@@ -429,16 +428,26 @@ class WCML_Products_UI extends WPML_Templates_Factory {
429
  $sql .= " AND (";
430
  switch($translation_status){
431
  case 'not':
432
- $wheres = array();
433
  foreach($this->sitepress->get_active_languages() as $lang){
434
  if($lang['code'] == $slang) continue;
435
  $tbl_alias_suffix = str_replace('-','_',$lang['code']);
436
- $sql .= "( p.ID IN ( SELECT iclt_orig.element_id FROM {$wpdb->prefix}icl_translations iclt_orig LEFT JOIN {$wpdb->prefix}icl_translations iclt_{$tbl_alias_suffix}
437
- ON iclt_{$tbl_alias_suffix}.trid=iclt_orig.trid AND iclt_{$tbl_alias_suffix}.language_code='{$lang['code']}' WHERE iclt_orig.source_language_code IS NULL and iclt_{$tbl_alias_suffix}.element_id IS NULL ) ) OR\n";
 
 
 
 
 
 
 
 
 
 
 
 
438
  }
439
  break;
440
  case ( $translation_status == 'need_update' || $translation_status == 'not' ):
441
- $wheres = array();
442
  foreach($this->sitepress->get_active_languages() as $lang){
443
  if($lang['code'] == $slang) continue;
444
  $tbl_alias_suffix = str_replace('-','_',$lang['code']);
@@ -446,7 +455,6 @@ class WCML_Products_UI extends WPML_Templates_Factory {
446
  }
447
  break;
448
  case 'in_progress':
449
- $wheres = array();
450
  foreach($this->sitepress->get_active_languages() as $lang){
451
  if($lang['code'] == $slang) continue;
452
  $tbl_alias_suffix = str_replace('-','_',$lang['code']);
120
  }
121
 
122
  public function get_products_data(){
 
123
 
124
  $active_languages = $this->sitepress->get_active_languages();
125
 
126
  $products_info = $this->get_product_info_from_self_edit_mode();
 
127
  if( !$products_info ){
128
  $products_info = $this->get_product_info_for_translators();
129
  }
 
130
  if( !$products_info ){
131
  $products_info = $this->get_products_from_filter();
132
  }
207
 
208
  if ( isset( $_GET[ 'prid' ] ) ) {
209
 
210
+ $prid = sanitize_text_field( $_GET[ 'prid' ] );
211
+
212
+ if ( ! $this->woocommerce_wpml->products->is_original_product( $prid ) ){
213
+ $products[] = get_post( $this->woocommerce_wpml->products->get_original_product_id( $prid ) );
214
  } else {
215
+ $products[] = get_post( $prid );
216
  }
217
  $products_count = 1;
218
 
388
  $sql .= " LEFT JOIN {$wpdb->prefix}icl_translations AS t ON t.element_id = p.id";
389
 
390
  if(in_array($translation_status,array('not','need_update','in_progress','complete'))){
391
+
392
  foreach($this->sitepress->get_active_languages() as $lang){
393
 
394
  if( $lang['code'] == $slang ) continue;
428
  $sql .= " AND (";
429
  switch($translation_status){
430
  case 'not':
 
431
  foreach($this->sitepress->get_active_languages() as $lang){
432
  if($lang['code'] == $slang) continue;
433
  $tbl_alias_suffix = str_replace('-','_',$lang['code']);
434
+ $sql .= sprintf( "( p.ID iN (
435
+ SELECT iclt_orig.element_id
436
+ FROM {$wpdb->prefix}icl_translations iclt_orig
437
+ LEFT JOIN {$wpdb->prefix}icl_translations iclt_%s
438
+ ON iclt_%s.trid= iclt_orig.trid AND
439
+ iclt_%s.language_code='%s'
440
+ WHERE iclt_orig.source_language_code IS NULL AND
441
+ iclt_%s.element_id IS NULL AND
442
+ iclt_%s.element_type IN ('post_product', 'post_product_variation')
443
+ )
444
+ ) OR ",
445
+ esc_sql( $tbl_alias_suffix ), esc_sql( $tbl_alias_suffix ), esc_sql( $tbl_alias_suffix ),
446
+ esc_sql( $lang['code'] ), esc_sql( $tbl_alias_suffix ), esc_sql( $tbl_alias_suffix )
447
+ );
448
  }
449
  break;
450
  case ( $translation_status == 'need_update' || $translation_status == 'not' ):
 
451
  foreach($this->sitepress->get_active_languages() as $lang){
452
  if($lang['code'] == $slang) continue;
453
  $tbl_alias_suffix = str_replace('-','_',$lang['code']);
455
  }
456
  break;
457
  case 'in_progress':
 
458
  foreach($this->sitepress->get_active_languages() as $lang){
459
  if($lang['code'] == $slang) continue;
460
  $tbl_alias_suffix = str_replace('-','_',$lang['code']);
inc/template-classes/class-wcml-troubleshooting-ui.php CHANGED
@@ -26,6 +26,7 @@ class WCML_Troubleshooting_UI extends WPML_Templates_Factory {
26
  'prod_with_variations' => $this->woocommerce_wpml->troubleshooting->wcml_count_products_with_variations(),
27
  'prod_count' => $this->woocommerce_wpml->troubleshooting->wcml_count_products_for_gallery_sync(),
28
  'prod_categories_count' => $this->woocommerce_wpml->troubleshooting->wcml_count_product_categories(),
 
29
  'all_products_taxonomies' => $this->get_all_products_taxonomies(),
30
  'product_type_sync_needed' => !empty( $translated_product_type_terms ) ? true : false,
31
  'media_def' => defined('WPML_MEDIA_VERSION'),
@@ -43,6 +44,7 @@ class WCML_Troubleshooting_UI extends WPML_Templates_Factory {
43
  'none' => __( 'none', 'woocommerce-multilingual' ),
44
  'start' => __( 'Start', 'woocommerce-multilingual' ),
45
  'delete_terms' => __( 'Fix product_type taxonomy terms', 'woocommerce-multilingual' ),
 
46
  'product_type_fix_done' => __( 'Done!', 'woocommerce-multilingual' )
47
  ),
48
  'nonces' => array(
@@ -52,6 +54,7 @@ class WCML_Troubleshooting_UI extends WPML_Templates_Factory {
52
  'trbl_sync_categories' => wp_nonce_field('trbl_sync_categories', 'trbl_sync_categories_nonce'),
53
  'trbl_duplicate_terms' => wp_nonce_field('trbl_duplicate_terms', 'trbl_duplicate_terms_nonce'),
54
  'trbl_product_type_terms' => wp_nonce_field('trbl_product_type_terms', 'trbl_product_type_terms_nonce'),
 
55
  )
56
  );
57
 
26
  'prod_with_variations' => $this->woocommerce_wpml->troubleshooting->wcml_count_products_with_variations(),
27
  'prod_count' => $this->woocommerce_wpml->troubleshooting->wcml_count_products_for_gallery_sync(),
28
  'prod_categories_count' => $this->woocommerce_wpml->troubleshooting->wcml_count_product_categories(),
29
+ 'sync_stock_count' => $this->woocommerce_wpml->troubleshooting->wcml_count_product_stock_sync(),
30
  'all_products_taxonomies' => $this->get_all_products_taxonomies(),
31
  'product_type_sync_needed' => !empty( $translated_product_type_terms ) ? true : false,
32
  'media_def' => defined('WPML_MEDIA_VERSION'),
44
  'none' => __( 'none', 'woocommerce-multilingual' ),
45
  'start' => __( 'Start', 'woocommerce-multilingual' ),
46
  'delete_terms' => __( 'Fix product_type taxonomy terms', 'woocommerce-multilingual' ),
47
+ 'sync_stock' => __( 'Sync product stock quantity and status ( synchronizing min stock between translations )', 'woocommerce-multilingual' ),
48
  'product_type_fix_done' => __( 'Done!', 'woocommerce-multilingual' )
49
  ),
50
  'nonces' => array(
54
  'trbl_sync_categories' => wp_nonce_field('trbl_sync_categories', 'trbl_sync_categories_nonce'),
55
  'trbl_duplicate_terms' => wp_nonce_field('trbl_duplicate_terms', 'trbl_duplicate_terms_nonce'),
56
  'trbl_product_type_terms' => wp_nonce_field('trbl_product_type_terms', 'trbl_product_type_terms_nonce'),
57
+ 'trbl_sync_stock' => wp_nonce_field('trbl_sync_stock', 'trbl_sync_stock_nonce'),
58
  )
59
  );
60
 
inc/template-classes/status/class-wcml-status-status-ui.php CHANGED
@@ -17,7 +17,7 @@ class WCML_Status_Status_UI extends WPML_Templates_Factory {
17
  'media_version' => defined( 'WPML_MEDIA_VERSION' ),
18
  'tm_version' => defined( 'WPML_TM_VERSION' ),
19
  'st_version' => defined( 'WPML_ST_VERSION' ),
20
- 'wc' => class_exists( 'Woocommerce' ),
21
  'icl_setup' => $this->sitepress->setup(),
22
  'strings' => array(
23
  'status' => __( 'Plugins Status', 'woocommerce-multilingual' ),
17
  'media_version' => defined( 'WPML_MEDIA_VERSION' ),
18
  'tm_version' => defined( 'WPML_TM_VERSION' ),
19
  'st_version' => defined( 'WPML_ST_VERSION' ),
20
+ 'wc' => class_exists( 'WooCommerce' ),
21
  'icl_setup' => $this->sitepress->setup(),
22
  'strings' => array(
23
  'status' => __( 'Plugins Status', 'woocommerce-multilingual' ),
inc/translation-editor/class-wcml-editor-ui-product-job.php CHANGED
@@ -100,7 +100,16 @@ class WCML_Editor_UI_Product_Job extends WPML_Editor_UI_Job {
100
 
101
  $this->add_field( new WPML_Editor_UI_Single_Line_Field( 'title', __( 'Title', 'woocommerce-multilingual' ), $this->data, true ) );
102
  $this->add_field( new WPML_Editor_UI_Single_Line_Field( 'slug', __( 'Slug', 'woocommerce-multilingual' ), $this->data, true ) );
103
- $this->add_field( new WCML_Editor_UI_WYSIWYG_Field( 'product_content', __( 'Content / Description', 'woocommerce-multilingual' ), $this->data, true ) );
 
 
 
 
 
 
 
 
 
104
 
105
  $excerpt_section = new WPML_Editor_UI_Field_Section( __( 'Excerpt', 'woocommerce-multilingual' ) );
106
  $excerpt_section->add_field( new WCML_Editor_UI_WYSIWYG_Field( 'product_excerpt', null, $this->data, true ) );
@@ -307,7 +316,6 @@ class WCML_Editor_UI_Product_Job extends WPML_Editor_UI_Job {
307
 
308
  $element_data = array( 'title' => array( 'original' => $this->original_post->post_title ),
309
  'slug' => array( 'original' => urldecode( $this->original_post->post_name ) ),
310
- 'product_content' => array( 'original' => $this->original_post->post_content ),
311
  'product_excerpt' => array( 'original' => $this->original_post->post_excerpt ),
312
  '_purchase_note' => array( 'original' => get_post_meta( $this->product_id, '_purchase_note', true ) )
313
  );
@@ -315,11 +323,21 @@ class WCML_Editor_UI_Product_Job extends WPML_Editor_UI_Job {
315
  if ( $translation ) {
316
  $element_data[ 'title' ][ 'translation' ] = $translation->post_title;
317
  $element_data[ 'slug' ][ 'translation' ] = urldecode( $translation->post_name );
318
- $element_data[ 'product_content' ][ 'translation' ] = $translation->post_content;
319
  $element_data[ 'product_excerpt' ][ 'translation' ] = $translation->post_excerpt;
320
  $element_data[ '_purchase_note' ][ 'translation' ] = get_post_meta( $translation->ID, '_purchase_note', true );
321
  }
322
 
 
 
 
 
 
 
 
 
 
 
 
323
  $product_images = $this->woocommerce_wpml->media->product_images_ids( $this->product_id );
324
  foreach( $product_images as $image_id ) {
325
  $attachment_data = $this->wpdb->get_row( $this->wpdb->prepare( "SELECT post_title,post_excerpt,post_content FROM {$this->wpdb->posts} WHERE ID = %d", $image_id ) );
@@ -497,7 +515,7 @@ class WCML_Editor_UI_Product_Job extends WPML_Editor_UI_Job {
497
  $args[ 'post_title' ] = $translations[ md5( 'title' ) ];
498
  $args[ 'post_name' ] = $translations[ md5( 'slug' ) ];
499
  $args[ 'post_type' ] = $this->original_post->post_type;
500
- $args[ 'post_content' ] = $translations[ md5( 'product_content' ) ];
501
  $args[ 'post_excerpt' ] = $translations[ md5( 'product_excerpt' ) ];
502
 
503
  if ( !$args[ 'post_title' ] && !$args[ 'post_content' ] && !$args[ 'post_excerpt' ] ){
@@ -550,7 +568,7 @@ class WCML_Editor_UI_Product_Job extends WPML_Editor_UI_Job {
550
  $args = array();
551
  $args[ 'ID' ] = $tr_product_id;
552
  $args[ 'post_title' ] = $translations[ md5( 'title' ) ];
553
- $args[ 'post_content' ] = $translations[ md5( 'product_content' ) ];
554
  $args[ 'post_excerpt' ] = $translations[ md5( 'product_excerpt' ) ];
555
  $args[ 'post_status' ] = $this->original_post->post_status;
556
  $args[ 'ping_status' ] = $this->original_post->ping_status;
@@ -585,6 +603,8 @@ class WCML_Editor_UI_Product_Job extends WPML_Editor_UI_Job {
585
 
586
  $this->woocommerce_wpml->sync_product_data->duplicate_product_post_meta( $this->product_id, $tr_product_id, $translations );
587
 
 
 
588
  $this->save_translated_terms( );
589
  //sync taxonomies
590
  $this->woocommerce_wpml->sync_product_data->sync_product_taxonomies( $this->product_id, $tr_product_id, $this->get_target_language() );
@@ -792,6 +812,8 @@ class WCML_Editor_UI_Product_Job extends WPML_Editor_UI_Job {
792
  }
793
  }
794
 
 
 
795
  public function requires_translation_complete_for_each_field() {
796
  return false;
797
  }
100
 
101
  $this->add_field( new WPML_Editor_UI_Single_Line_Field( 'title', __( 'Title', 'woocommerce-multilingual' ), $this->data, true ) );
102
  $this->add_field( new WPML_Editor_UI_Single_Line_Field( 'slug', __( 'Slug', 'woocommerce-multilingual' ), $this->data, true ) );
103
+
104
+ if( $this->woocommerce_wpml->page_builders->get_page_builders_string_packages( $this->product_id ) ){
105
+ $page_builders_strings_section = $this->woocommerce_wpml->page_builders->get_page_builders_strings_section( $this->data, $this->product_id, $this->get_target_language() );
106
+
107
+ if( $page_builders_strings_section ){
108
+ $this->add_field( $page_builders_strings_section );
109
+ }
110
+ }else{
111
+ $this->add_field( new WCML_Editor_UI_WYSIWYG_Field( 'product_content', __( 'Content / Description', 'woocommerce-multilingual' ), $this->data, true ) );
112
+ }
113
 
114
  $excerpt_section = new WPML_Editor_UI_Field_Section( __( 'Excerpt', 'woocommerce-multilingual' ) );
115
  $excerpt_section->add_field( new WCML_Editor_UI_WYSIWYG_Field( 'product_excerpt', null, $this->data, true ) );
316
 
317
  $element_data = array( 'title' => array( 'original' => $this->original_post->post_title ),
318
  'slug' => array( 'original' => urldecode( $this->original_post->post_name ) ),
 
319
  'product_excerpt' => array( 'original' => $this->original_post->post_excerpt ),
320
  '_purchase_note' => array( 'original' => get_post_meta( $this->product_id, '_purchase_note', true ) )
321
  );
323
  if ( $translation ) {
324
  $element_data[ 'title' ][ 'translation' ] = $translation->post_title;
325
  $element_data[ 'slug' ][ 'translation' ] = urldecode( $translation->post_name );
 
326
  $element_data[ 'product_excerpt' ][ 'translation' ] = $translation->post_excerpt;
327
  $element_data[ '_purchase_note' ][ 'translation' ] = get_post_meta( $translation->ID, '_purchase_note', true );
328
  }
329
 
330
+ if( $this->woocommerce_wpml->page_builders->get_page_builders_string_packages( $this->product_id ) ){
331
+ $element_data = $this->woocommerce_wpml->page_builders->page_builders_data( $element_data, $this->product_id, $this->get_target_language() );
332
+ }else{
333
+ $element_data[ 'product_content' ] = array(
334
+ 'original' => $this->original_post->post_content
335
+ );
336
+ if ( $translation ) {
337
+ $element_data[ 'product_content' ][ 'translation' ] = $translation->post_content;
338
+ }
339
+ }
340
+
341
  $product_images = $this->woocommerce_wpml->media->product_images_ids( $this->product_id );
342
  foreach( $product_images as $image_id ) {
343
  $attachment_data = $this->wpdb->get_row( $this->wpdb->prepare( "SELECT post_title,post_excerpt,post_content FROM {$this->wpdb->posts} WHERE ID = %d", $image_id ) );
515
  $args[ 'post_title' ] = $translations[ md5( 'title' ) ];
516
  $args[ 'post_name' ] = $translations[ md5( 'slug' ) ];
517
  $args[ 'post_type' ] = $this->original_post->post_type;
518
+ $args[ 'post_content' ] = isset( $translations[ md5( 'product_content' ) ] ) ? $translations[ md5( 'product_content' ) ] : '';
519
  $args[ 'post_excerpt' ] = $translations[ md5( 'product_excerpt' ) ];
520
 
521
  if ( !$args[ 'post_title' ] && !$args[ 'post_content' ] && !$args[ 'post_excerpt' ] ){
568
  $args = array();
569
  $args[ 'ID' ] = $tr_product_id;
570
  $args[ 'post_title' ] = $translations[ md5( 'title' ) ];
571
+ $args[ 'post_content' ] = isset( $translations[ md5( 'product_content' ) ] ) ? $translations[ md5( 'product_content' ) ] : '';
572
  $args[ 'post_excerpt' ] = $translations[ md5( 'product_excerpt' ) ];
573
  $args[ 'post_status' ] = $this->original_post->post_status;
574
  $args[ 'ping_status' ] = $this->original_post->ping_status;
603
 
604
  $this->woocommerce_wpml->sync_product_data->duplicate_product_post_meta( $this->product_id, $tr_product_id, $translations );
605
 
606
+ $this->woocommerce_wpml->page_builders->save_page_builders_strings( $translations, $this->product_id, $this->get_target_language() );
607
+
608
  $this->save_translated_terms( );
609
  //sync taxonomies
610
  $this->woocommerce_wpml->sync_product_data->sync_product_taxonomies( $this->product_id, $tr_product_id, $this->get_target_language() );
812
  }
813
  }
814
 
815
+
816
+
817
  public function requires_translation_complete_for_each_field() {
818
  return false;
819
  }
inc/translation-editor/class-wcml-page-builders.php ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WCML_Page_Builders{
4
+
5
+ /**
6
+ * @var SitePress
7
+ */
8
+ private $sitepress;
9
+
10
+ function __construct( &$sitepress )
11
+ {
12
+ $this->sitepress = $sitepress;
13
+
14
+ }
15
+
16
+ public function get_page_builders_string_packages( $product_id ){
17
+ return apply_filters( 'wpml_st_get_post_string_packages', false, $product_id );
18
+ }
19
+
20
+ public function get_page_builders_strings( $product_id, $target_language ){
21
+
22
+ $string_packages = $this->get_page_builders_string_packages( $product_id );
23
+ $translation_package = array();
24
+
25
+ if ( $string_packages ) {
26
+
27
+ foreach ( $string_packages as $package_id => $string_package ) {
28
+
29
+ $translation_package[ $package_id ] = array(
30
+ 'title' => $string_package->title
31
+ );
32
+
33
+ $strings = $string_package->get_package_strings();
34
+
35
+ $translated_strings = $string_package->get_translated_strings( array() );
36
+
37
+ foreach ( $strings as $string ) {
38
+
39
+ if( isset( $translated_strings[ $string->name ][ $target_language ] ) ){
40
+ $string->translated_value = $translated_strings[ $string->name ][ $target_language ][ 'value' ];
41
+ }
42
+
43
+ $string->name = WPML_TM_Page_Builders_Field_Wrapper::generate_field_slug( $package_id, $string->id );
44
+
45
+ $translation_package[ $package_id ][ 'strings' ][] = $string;
46
+ }
47
+ }
48
+ }
49
+
50
+ return $translation_package;
51
+
52
+ }
53
+
54
+ public function get_page_builders_strings_section( $data, $product_id, $target_language ){
55
+
56
+ $string_packages = $this->get_page_builders_strings( $product_id, $target_language );
57
+ $strings_section = false;
58
+
59
+ foreach ( $string_packages as $string_package ){
60
+ $strings_section = new WPML_Editor_UI_Field_Section( $string_package[ 'title' ] );
61
+
62
+ foreach ( $string_package[ 'strings' ] as $string ) {
63
+ $field_label = apply_filters( 'wpml_string_title_from_id', false, $string->id );
64
+ $strings_section->add_field( new WCML_Editor_UI_WYSIWYG_Field( $string->name, $field_label, $data, true ) );
65
+ }
66
+ }
67
+
68
+ return $strings_section;
69
+ }
70
+
71
+ public function page_builders_data( $element_data, $product_id, $target_language ){
72
+
73
+ $string_packages = $this->get_page_builders_strings( $product_id, $target_language );
74
+
75
+ foreach ( $string_packages as $string_package ){
76
+
77
+ foreach ( $string_package[ 'strings' ] as $string ) {
78
+ $element_data[ $string->name ] = array( 'original' => $string->value );
79
+ if( isset( $string->translated_value ) ){
80
+ $element_data[ $string->name ][ 'translation' ] = $string->translated_value;
81
+ }
82
+ }
83
+ }
84
+
85
+ return $element_data;
86
+ }
87
+
88
+ public function save_page_builders_strings( $translations, $product_id, $target_language ){
89
+
90
+ $string_packages = $this->get_page_builders_strings( $product_id, $target_language );
91
+
92
+ foreach ( $string_packages as $string_package ){
93
+
94
+ foreach ( $string_package[ 'strings' ] as $string ) {
95
+
96
+ do_action(
97
+ 'wpml_add_string_translation',
98
+ $string->id,
99
+ $target_language,
100
+ $translations[ md5( $string->name ) ],
101
+ $this->sitepress->get_wp_api()->constant( 'ICL_TM_COMPLETE' )
102
+ );
103
+
104
+ }
105
+ }
106
+ }
107
+ }
inc/translation-editor/class-wcml-synchronize-product-data.php CHANGED
@@ -22,12 +22,6 @@ class WCML_Synchronize_Product_Data{
22
 
23
  add_filter( 'icl_make_duplicate', array( $this, 'icl_make_duplicate'), 110, 4 );
24
 
25
- if( ( defined('WC_VERSION') && version_compare( WC_VERSION , '2.7', '<' ) ) ) {
26
- add_action('woocommerce_duplicate_product', array($this, 'woocommerce_duplicate_product'), 10, 2);
27
- }else{
28
- add_action( 'woocommerce_product_duplicate', array( $this, 'woocommerce_duplicate_product' ), 10, 2 );
29
- }
30
-
31
  //quick & bulk edit
32
  add_action( 'woocommerce_product_quick_edit_save', array( $this, 'woocommerce_product_quick_edit_save' ) );
33
  add_action( 'woocommerce_product_bulk_edit_save', array( $this, 'woocommerce_product_quick_edit_save' ) );
@@ -53,7 +47,7 @@ class WCML_Synchronize_Product_Data{
53
 
54
  $original_language = $this->woocommerce_wpml->products->get_original_product_language( $post_id );
55
  $current_language = $this->sitepress->get_current_language();
56
- $original_product_id = apply_filters( 'translate_object_id', $post_id, 'product', false, $original_language );
57
 
58
  $wpml_media_options = maybe_unserialize( get_option( '_wpml_media' ) );
59
 
@@ -395,8 +389,7 @@ class WCML_Synchronize_Product_Data{
395
  public function icl_make_duplicate( $master_post_id, $lang, $postarr, $id ){
396
  if( get_post_type( $master_post_id ) == 'product' ){
397
 
398
- $original_language = $this->woocommerce_wpml->products->get_original_product_language( $master_post_id );
399
- $master_post_id = apply_filters( 'translate_object_id', $master_post_id, 'product', false, $original_language );
400
 
401
  $this->sync_product_data( $master_post_id, $id, $lang );
402
  }
@@ -492,77 +485,6 @@ class WCML_Synchronize_Product_Data{
492
  return $post_fields;
493
  }
494
 
495
- public function woocommerce_duplicate_product( $new_id, $post ){
496
- $duplicated_products = array();
497
-
498
- //duplicate original first
499
- $trid = $this->sitepress->get_element_trid( $post->ID, 'post_' . $post->post_type );
500
- $orig_id = $this->sitepress->get_original_element_id_by_trid( $trid );
501
- $orig_lang = $this->woocommerce_wpml->products->get_original_product_language( $post->ID );
502
-
503
- $wc_admin = new WC_Admin_Duplicate_Product();
504
-
505
- if( $orig_id == $post->ID ){
506
- $this->sitepress->set_element_language_details( $new_id, 'post_' . $post->post_type, false, $orig_lang );
507
- $new_trid = $this->sitepress->get_element_trid( $new_id, 'post_' . $post->post_type );
508
- $new_orig_id = $new_id;
509
- }else{
510
- $post_to_duplicate = $this->wpdb->get_row( $this->wpdb->prepare( "SELECT * FROM {$this->wpdb->posts} WHERE ID=%d", $orig_id ) );
511
- if ( ! empty( $post_to_duplicate ) ) {
512
- $new_orig_id = $wc_admin->duplicate_product( $post_to_duplicate );
513
- do_action( 'wcml_after_duplicate_product' , $new_id, $post_to_duplicate );
514
- $this->sitepress->set_element_language_details( $new_orig_id, 'post_' . $post->post_type, false, $orig_lang );
515
- $new_trid = $this->sitepress->get_element_trid( $new_orig_id, 'post_' . $post->post_type );
516
- if( get_post_meta( $orig_id, '_icl_lang_duplicate_of' ) ){
517
- update_post_meta( $new_id, '_icl_lang_duplicate_of', $new_orig_id );
518
- }
519
- $this->sitepress->set_element_language_details( $new_id, 'post_' . $post->post_type, $new_trid, $this->sitepress->get_current_language() );
520
- }
521
- }
522
-
523
- // Set language info for variations
524
- if ( $children_products = get_children( 'post_parent=' . $new_orig_id . '&post_type=product_variation' ) ) {
525
- foreach ( $children_products as $child ) {
526
- $this->sitepress->set_element_language_details( $child->ID, 'post_product_variation', false, $orig_lang );
527
- }
528
- }
529
-
530
- $translations = $this->sitepress->get_element_translations( $trid, 'post_' . $post->post_type );
531
- $duplicated_products[ 'translations' ] = array();
532
- if( $translations ){
533
- foreach( $translations as $translation ){
534
- if( !$translation->original && $translation->element_id != $post->ID ){
535
- $post_to_duplicate = $this->wpdb->get_row( $this->wpdb->prepare( "SELECT * FROM {$this->wpdb->posts} WHERE ID=%d", $translation->element_id ) );
536
-
537
- if( ! empty( $post_to_duplicate ) ) {
538
- $new_id = $wc_admin->duplicate_product( $post_to_duplicate );
539
- $new_id_obj = get_post( $new_id );
540
- $new_slug = wp_unique_post_slug( sanitize_title( $new_id_obj->post_title ), $new_id, $post_to_duplicate->post_status, $post_to_duplicate->post_type, $new_id_obj->post_parent );
541
-
542
- $this->wpdb->update(
543
- $this->wpdb->posts,
544
- array(
545
- 'post_name' => $new_slug,
546
- 'post_status' => 'draft'
547
- ),
548
- array( 'ID' => $new_id )
549
- );
550
-
551
- do_action( 'wcml_after_duplicate_product' , $new_id, $post_to_duplicate );
552
- $this->sitepress->set_element_language_details( $new_id, 'post_' . $post->post_type, $new_trid, $translation->language_code );
553
- if( get_post_meta( $translation->element_id, '_icl_lang_duplicate_of' ) ){
554
- update_post_meta( $new_id, '_icl_lang_duplicate_of', $new_orig_id );
555
- }
556
- $duplicated_products[ 'translations' ][] = $new_id;
557
- }
558
- }
559
- }
560
- }
561
-
562
- $duplicated_products[ 'original' ] = $new_orig_id;
563
-
564
- return $duplicated_products;
565
- }
566
 
567
  public function icl_connect_translations_action(){
568
  if( isset( $_POST[ 'icl_ajx_action' ] ) && $_POST[ 'icl_ajx_action' ] == 'connect_translations' ) {
22
 
23
  add_filter( 'icl_make_duplicate', array( $this, 'icl_make_duplicate'), 110, 4 );
24
 
 
 
 
 
 
 
25
  //quick & bulk edit
26
  add_action( 'woocommerce_product_quick_edit_save', array( $this, 'woocommerce_product_quick_edit_save' ) );
27
  add_action( 'woocommerce_product_bulk_edit_save', array( $this, 'woocommerce_product_quick_edit_save' ) );
47
 
48
  $original_language = $this->woocommerce_wpml->products->get_original_product_language( $post_id );
49
  $current_language = $this->sitepress->get_current_language();
50
+ $original_product_id = $this->woocommerce_wpml->products->get_original_product_id( $post_id );
51
 
52
  $wpml_media_options = maybe_unserialize( get_option( '_wpml_media' ) );
53
 
389
  public function icl_make_duplicate( $master_post_id, $lang, $postarr, $id ){
390
  if( get_post_type( $master_post_id ) == 'product' ){
391
 
392
+ $master_post_id = $this->woocommerce_wpml->products->get_original_product_id( $master_post_id );
 
393
 
394
  $this->sync_product_data( $master_post_id, $id, $lang );
395
  }
485
  return $post_fields;
486
  }
487
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
488
 
489
  public function icl_connect_translations_action(){
490
  if( isset( $_POST[ 'icl_ajx_action' ] ) && $_POST[ 'icl_ajx_action' ] == 'connect_translations' ) {
inc/translation-editor/class-wcml-synchronize-variations-data.php CHANGED
@@ -256,7 +256,7 @@ class WCML_Synchronize_Variations_Data{
256
  if( $meta_key == '_stock'){
257
  $this->update_stock_quantity( $variation_id, $meta_value );
258
  }else{
259
- update_post_meta( $variation_id, $meta_key, $meta_value );
260
  }
261
  }elseif ( !isset( $settings[ $meta_key ] ) || $settings[ $meta_key ] == WPML_IGNORE_CUSTOM_FIELD ) {
262
  continue;
256
  if( $meta_key == '_stock'){
257
  $this->update_stock_quantity( $variation_id, $meta_value );
258
  }else{
259
+ update_post_meta( $variation_id, $meta_key, maybe_unserialize( $meta_value ) );
260
  }
261
  }elseif ( !isset( $settings[ $meta_key ] ) || $settings[ $meta_key ] == WPML_IGNORE_CUSTOM_FIELD ) {
262
  continue;
inc/translation-editor/class-wcml-translation-editor.php CHANGED
@@ -216,13 +216,12 @@ class WCML_Translation_Editor{
216
  );
217
 
218
  $variations = get_posts( $args );
219
- $original_language = $this->woocommerce_wpml->products->get_original_product_language( $product_id );
220
  $file_path_sync = array();
221
 
222
  if ( $variations ) {
223
  foreach ($variations as $variation) {
224
  $variation_id = absint( $variation->ID );
225
- $original_id = apply_filters( 'translate_object_id', $variation_id, 'product_variation', true, $original_language );
226
  $custom_product_sync = get_post_meta( $original_id, 'wcml_sync_files', true );
227
  if( $custom_product_sync && $custom_product_sync == 'self' ) {
228
  $file_path_sync[ $variation_id ] = false;
216
  );
217
 
218
  $variations = get_posts( $args );
 
219
  $file_path_sync = array();
220
 
221
  if ( $variations ) {
222
  foreach ($variations as $variation) {
223
  $variation_id = absint( $variation->ID );
224
+ $original_id = $this->woocommerce_wpml->products->get_original_product_id( $product_id );
225
  $custom_product_sync = get_post_meta( $original_id, 'wcml_sync_files', true );
226
  if( $custom_product_sync && $custom_product_sync == 'self' ) {
227
  $file_path_sync[ $variation_id ] = false;
inc/translation-editor/class-wcml-wc-admin-duplicate-product.php ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WCML_WC_Admin_Duplicate_Product extends WC_Admin_Duplicate_Product{
4
+
5
+ /**
6
+ * @var woocommerce_wpml
7
+ */
8
+ private $woocommerce_wpml;
9
+ /**
10
+ * @var SitePress
11
+ */
12
+ private $sitepress;
13
+
14
+ public function __construct( &$woocommerce_wpml, &$sitepress, &$wpdb ) {
15
+
16
+ $this->woocommerce_wpml = $woocommerce_wpml;
17
+ $this->sitepress = $sitepress;
18
+ $this->wpdb = $wpdb;
19
+
20
+ if( ( defined('WC_VERSION') && version_compare( WC_VERSION , '3.0.0', '<' ) ) ) {
21
+ add_action('woocommerce_duplicate_product', array( $this, 'woocommerce_duplicate_product'), 10, 2);
22
+ }else{
23
+ add_action( 'woocommerce_product_duplicate', array( $this, 'woocommerce_duplicate_product' ), 10, 2 );
24
+ }
25
+
26
+ }
27
+
28
+ public function woocommerce_duplicate_product( $new_id, $post ){
29
+ $duplicated_products = array();
30
+
31
+ $product_id = WooCommerce_Functions_Wrapper::get_product_id( $post );
32
+ if( !is_numeric( $new_id ) ){
33
+ $new_id = WooCommerce_Functions_Wrapper::get_product_id( $new_id );
34
+ }
35
+
36
+ //duplicate original first
37
+ $trid = $this->sitepress->get_element_trid( $product_id, 'post_' . $post->post_type );
38
+ $orig_id = $this->sitepress->get_original_element_id_by_trid( $trid );
39
+ $orig_lang = $this->woocommerce_wpml->products->get_original_product_language($product_id );
40
+
41
+ if( $orig_id == $product_id ){
42
+ $this->sitepress->set_element_language_details( $new_id, 'post_' . $post->post_type, false, $orig_lang );
43
+ $new_trid = $this->sitepress->get_element_trid( $new_id, 'post_' . $post->post_type );
44
+ $new_orig_id = $new_id;
45
+ }else{
46
+ $post_to_duplicate = $this->wpdb->get_row( $this->wpdb->prepare( "SELECT * FROM {$this->wpdb->posts} WHERE ID=%d", $orig_id ) );
47
+ if ( ! empty( $post_to_duplicate ) ) {
48
+
49
+ $new_orig_id = $this->wc_duplicate_product( $post_to_duplicate );
50
+
51
+ do_action( 'wcml_after_duplicate_product' , $new_id, $post_to_duplicate );
52
+ $this->sitepress->set_element_language_details( $new_orig_id, 'post_' . $post->post_type, false, $orig_lang );
53
+ $new_trid = $this->sitepress->get_element_trid( $new_orig_id, 'post_' . $post->post_type );
54
+ if( get_post_meta( $orig_id, '_icl_lang_duplicate_of' ) ){
55
+ update_post_meta( $new_id, '_icl_lang_duplicate_of', $new_orig_id );
56
+ }
57
+ $this->sitepress->set_element_language_details( $new_id, 'post_' . $post->post_type, $new_trid, $this->sitepress->get_current_language() );
58
+ }
59
+ }
60
+
61
+ // Set language info for variations
62
+ if ( $children_products = get_children( 'post_parent=' . $new_orig_id . '&post_type=product_variation' ) ) {
63
+ foreach ( $children_products as $child ) {
64
+ $this->sitepress->set_element_language_details( $child->ID, 'post_product_variation', false, $orig_lang );
65
+ }
66
+ }
67
+
68
+ $translations = $this->sitepress->get_element_translations( $trid, 'post_' . $post->post_type );
69
+ $duplicated_products[ 'translations' ] = array();
70
+ if( $translations ){
71
+ foreach( $translations as $translation ){
72
+ if( !$translation->original && $translation->element_id != $product_id ){
73
+ $post_to_duplicate = $this->wpdb->get_row( $this->wpdb->prepare( "SELECT * FROM {$this->wpdb->posts} WHERE ID=%d", $translation->element_id ) );
74
+
75
+ if( ! empty( $post_to_duplicate ) ) {
76
+ $new_id = $this->wc_duplicate_product( $post_to_duplicate );
77
+ $new_id_obj = get_post( $new_id );
78
+ $new_slug = wp_unique_post_slug( sanitize_title( $new_id_obj->post_title ), $new_id, $post_to_duplicate->post_status, $post_to_duplicate->post_type, $new_id_obj->post_parent );
79
+
80
+ $this->wpdb->update(
81
+ $this->wpdb->posts,
82
+ array(
83
+ 'post_name' => $new_slug,
84
+ 'post_status' => 'draft'
85
+ ),
86
+ array( 'ID' => $new_id )
87
+ );
88
+
89
+ do_action( 'wcml_after_duplicate_product' , $new_id, $post_to_duplicate );
90
+ $this->sitepress->set_element_language_details( $new_id, 'post_' . $post->post_type, $new_trid, $translation->language_code );
91
+ if( get_post_meta( $translation->element_id, '_icl_lang_duplicate_of' ) ){
92
+ update_post_meta( $new_id, '_icl_lang_duplicate_of', $new_orig_id );
93
+ }
94
+ $duplicated_products[ 'translations' ][] = $new_id;
95
+ }
96
+ }
97
+ }
98
+ }
99
+
100
+ $duplicated_products[ 'original' ] = $new_orig_id;
101
+
102
+ return $duplicated_products;
103
+ }
104
+
105
+ public function wc_duplicate_product( $post_to_duplicate ){
106
+
107
+ $product = wc_get_product( $post_to_duplicate->ID );
108
+
109
+ if( WooCommerce_Functions_Wrapper::is_deprecated() ){
110
+ $new_orig_id = $this->duplicate_product( $product );
111
+ }else{
112
+ $duplicate = $this->product_duplicate( $product );
113
+ $new_orig_id = $duplicate->get_id();
114
+ }
115
+
116
+ return $new_orig_id;
117
+ }
118
+ }
inc/woocommerce-functions-wrapper.php CHANGED
@@ -4,7 +4,7 @@ class WooCommerce_Functions_Wrapper{
4
 
5
  public static function is_deprecated(){
6
 
7
- if( version_compare( WC_VERSION , '2.7', '<' ) ){
8
  return true;
9
  }else{
10
  return false;
@@ -63,6 +63,22 @@ class WooCommerce_Functions_Wrapper{
63
  return $order->get_currency();
64
  }
65
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
 
67
  }
68
 
4
 
5
  public static function is_deprecated(){
6
 
7
+ if( version_compare( WC_VERSION , '3.0.0', '<' ) ){
8
  return true;
9
  }else{
10
  return false;
63
  return $order->get_currency();
64
  }
65
  }
66
+
67
+ public static function get_item_downloads( $object, $item ){
68
+ if( self::is_deprecated() ){
69
+ return $object->get_item_downloads( $item );
70
+ }else{
71
+ return $item->get_item_downloads( );
72
+ }
73
+ }
74
+
75
+ public static function get_order_id( $order ){
76
+ if( self::is_deprecated() ){
77
+ return $order->id;
78
+ }else{
79
+ return $order->get_id();
80
+ }
81
+ }
82
 
83
  }
84
 
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.9
7
  Tested up to: 4.7.3
8
- Stable tag: 4.1.2
9
 
10
  Allows running fully multilingual e-commerce sites using WooCommerce and WPML.
11
 
@@ -142,6 +142,37 @@ WooCommerce Multilingual is compatible with all major WooCommerce extensions. We
142
 
143
  == Changelog ==
144
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
145
  = 4.1.2 =
146
  * Fixed the currency switcher not being displayed correctly when using the Storefront theme
147
  * Fixed an incompatibility with an older WPML version leading to a fatal error
5
  License: GPLv2
6
  Requires at least: 3.9
7
  Tested up to: 4.7.3
8
+ Stable tag: 4.1.3
9
 
10
  Allows running fully multilingual e-commerce sites using WooCommerce and WPML.
11
 
142
 
143
  == Changelog ==
144
 
145
+ = 4.1.3 =
146
+ * Improvements for the REST API support (compliant with WooCommerce REST API v2)
147
+ * Bug fix: Order confirmation emails were not translated correctly when using WooCommerce 3.0
148
+ * Bug fix: The admin language switcher was displayed in a wrong place when using the Swish
149
+ * Bug fix: Composite products were displaying the wrong price amount in secondary currencies
150
+ * Bug fix: Sometimes switching the currency on the front end didn't work when using a caching plugin
151
+ * Bug fix: Don't enforce the REST API support (added in 4.1) for legacy WooCommerce REST calls
152
+ * Bug fix: In some conditions, variations custom fields were double-serialized when copied to the translations
153
+ * Bug fix: Sometimes the currency switcher preview was not displaying correctly
154
+ * Bug fix: Manually adding a product to an order was sometimes causing a fatal error
155
+ * Bug fix: A fatal error was occurring when trying to translate a bookable product with Persons
156
+ * Bug fix: The RTL styles were loaded incorrectly on the translation management when Yoast SEO was active
157
+ * Bug fix: Trying to display the currency switcher with the 'do_action' function was causing a fatal error
158
+ * Bug fix: Product urls were incorrect when permalink structure was set to /index.php/%postname%/
159
+ * Bug fix: Product variation custom fields were double-serialized when copied to translations
160
+ * Bug fix: Language switcher was misplaced when using the Swish Gateway extension
161
+ * Bug fix: Downloadable files were not available in secondary languages
162
+ * Bug fix: Using The Events Calendar without Tribe Tickets RSVP and Tribe Tickets Plus caused errors
163
+ * Bug fix: Incorrect currency was shown in the backend for orders placed in a secondary currency
164
+ * Bug fix: In some circumstances, the shipping tax was rounded incorrectly in the secondary currencies
165
+ * Bug fix: After duplicating a variable product, the variations weren't showing on the translated product edit page
166
+ * Added the option to synchronize the products stock information on the troubleshooting section
167
+ * Fixed a compatibility issue with WooCommerce Bookings and WooCommerce Product addons (both active)
168
+ * Fixed a compatibility issue with WooCommerce Subscriptions (shipping costs incorrectly displayed)
169
+ * Fixed a compatibility issue with WooCommerce Product Bundles (removed items were not synced with translations)
170
+ * Fixed a compatibility issue with WooCommerce Membership
171
+ * Fixed a compatibility issue with WooCommerce Print Invoices/Packing Lists (PHP notices and possible a fatal error)
172
+ * Fixed compatibility issues with Aelia Currency Switcher and Aelia Foundation
173
+ * Fixed a compatibility issue with Visual Composer: shortcodes were not parsed in the translation editor
174
+
175
+
176
  = 4.1.2 =
177
  * Fixed the currency switcher not being displayed correctly when using the Storefront theme
178
  * Fixed an incompatibility with an older WPML version leading to a fatal error
res/js/dialogs.js CHANGED
@@ -64,7 +64,6 @@ jQuery( function($){
64
  },
65
  open: function (event) {
66
  $('body').css('overflow', 'hidden');
67
- WCML_Dialog._repositionDialog();
68
 
69
  if( data.class === 'wcml-cs-dialog' ){
70
  WCML_Dialog._attachDialogScrollEvent();
@@ -85,9 +84,12 @@ jQuery( function($){
85
  if(WCML_Dialog.using_wpdialog){ // pre WP 3.5
86
  dialog_div.wpdialog(dialog_parameters);
87
  }else{
88
- dialog_div.dialog(dialog_parameters);
 
 
 
 
89
  }
90
-
91
  }
92
 
93
  var resizeWindowEvent = _.debounce(function() {
@@ -97,9 +99,6 @@ jQuery( function($){
97
  }
98
  }, 200);
99
 
100
- $(window).resize(resizeWindowEvent);
101
-
102
-
103
  if(WCML_Dialog.using_wpdialog) { // pre WP 3.5
104
  dialog_div.wpdialog('open');
105
  }else{
@@ -133,6 +132,8 @@ jQuery( function($){
133
  WCML_Tooltip.init();
134
  }
135
 
 
 
136
  return false;
137
  }
138
 
64
  },
65
  open: function (event) {
66
  $('body').css('overflow', 'hidden');
 
67
 
68
  if( data.class === 'wcml-cs-dialog' ){
69
  WCML_Dialog._attachDialogScrollEvent();
84
  if(WCML_Dialog.using_wpdialog){ // pre WP 3.5
85
  dialog_div.wpdialog(dialog_parameters);
86
  }else{
87
+ dialog_div.dialog(
88
+ dialog_parameters
89
+ ).on('dialogopen', function () {
90
+ WCML_Dialog._repositionDialog();
91
+ });
92
  }
 
93
  }
94
 
95
  var resizeWindowEvent = _.debounce(function() {
99
  }
100
  }, 200);
101
 
 
 
 
102
  if(WCML_Dialog.using_wpdialog) { // pre WP 3.5
103
  dialog_div.wpdialog('open');
104
  }else{
132
  WCML_Tooltip.init();
133
  }
134
 
135
+ $(window).resize(resizeWindowEvent);
136
+
137
  return false;
138
  }
139
 
res/js/dialogs.min.js CHANGED
@@ -1 +1 @@
1
- var WCML_Dialog=WCML_Dialog||{};jQuery(function(a){var b;WCML_Dialog.dialog=function(c,d){var e=this;void 0===c&&(c="generic"),e.overflow_y=a("body").css("overflow-y"),a("body").css("overflow-y","hidden"),b=a("#wcml-dialog-"+c);var f=a("#"+c).attr("title");if(void 0===f&&(f="undefined"!=d.title?d.title:""),void 0===d.class&&(d.class=""),void 0===d.draggable&&(d.draggable=!1),!b.length){a(document.body).append(a('<div class="wcml-dialog-container" title="'+f+'" id="wcml-dialog-'+c+'" />')),b=a("#wcml-dialog-"+c);var g=a(window).height(),h={title:"",autoOpen:!1,show:!0,dialogClass:"wcml-ui-dialog otgs-ui-dialog "+d.class,position:{my:"center",at:"center",of:window},modal:!0,width:"90%",height:.7*g,resizable:!1,draggable:d.draggable,beforeOpen:function(a){},beforeClose:function(a){},close:function(b){a("body").css("overflow-y",e.overflow_y)},create:function(a){},focus:function(a){},open:function(b){a("body").css("overflow","hidden"),WCML_Dialog._repositionDialog(),"wcml-cs-dialog"===d.class&&WCML_Dialog._attachDialogScrollEvent()},refresh:function(a){}};void 0!==d.height&&"wcml-cs-dialog"!=d.class&&(h.height=Math.min(.7*g,d.height)),void 0!==d.width&&"wcml-cs-dialog"!=d.class&&(h.width=d.width),WCML_Dialog.using_wpdialog?b.wpdialog(h):b.dialog(h)}var i=_.debounce(function(){WCML_Dialog._repositionDialog(),"wcml-cs-dialog"===d.class&&WCML_Dialog._attachDialogScrollEvent()},200);if(a(window).resize(i),WCML_Dialog.using_wpdialog?b.wpdialog("open"):b.dialog("open"),d.action){var j=a('<div class="spinner"></div>');j.css({display:"inline-block",visibility:"visible",float:"none"}),b.html(j),a.ajax({url:ajaxurl,type:"post",dataType:"json",data:d,success:function(a){b.html(a.html)}})}return d.content&&a("#"+d.content).length&&b.html(a("#"+d.content).html()),"undefined"!=typeof WCML_Tooltip&&WCML_Tooltip.init(),!1},WCML_Dialog._repositionDialog=function(){var c=a(window).height()-180;b.css("max-height",c),b.dialog("option","position",{my:"center",at:"center",of:window})},WCML_Dialog._attachDialogScrollEvent=function(){var a=b.find(".wcml-currency-preview-wrapper"),c=b.width()>900,d=a.height()+200<b.height();d=d||c&&a.height()<b.height(),d?b.on("scroll.preview",function(){b.find(".wcml-currency-preview-wrapper").css({position:"relative",top:b.scrollTop()})}):b.off("scroll.preview").find(".wcml-currency-preview-wrapper").css({position:"relative",top:0})},WCML_Dialog._register_open_handler=function(){a(document).on("click",".js-wcml-dialog-trigger",function(b){b.preventDefault();var c=!1;a(this).data("dialog")?c=a(this).data("dialog"):a(this).data("action")&&(c=a(this).data("action")),c&&(a(this).data("action")&&a(this).data("action",a(this).data("action").replace(/-/g,"_")),WCML_Dialog.dialog(c,a(this).data()))}),a(document).on("click",".js-wcml-cs-dialog-trigger",function(b){b.preventDefault();var c=!1;a(this).data("dialog")&&(c=a(this).data("dialog"));var d=a(this).data();d.class="wcml-cs-dialog",d.draggable=!0,c&&(WCML_Dialog.dialog(c,d),WCML_Currency_Switcher_Settings.initColorPicker(),WCML_Currency_Switcher_Settings.currency_switcher_preview(a("#wcml-dialog-"+c)))})},WCML_Dialog._register_close_handler=function(){a(document).on("click",".wcml-dialog-close-button",function(b){b.preventDefault(),"undefined"!=typeof tinyMCE&&tinyMCE.triggerSave(),a(".wcml-dialog").find(".mce_editor textarea").each(function(){var b=a(this).attr("id"),c=a(this);if(b in tinyMCE.editors){var d=tinyMCE.get(b);d.isHidden()||c.val(d.getContent())}});var c=a(this).closest(".wcml-dialog-container"),d=a(this);d.attr("disabled","disabled");var e=a(this).data();if(e.action){var f=a('<div class="spinner"></div>');f.css({visibility:"visible",float:"right"}).prependTo(a(".wcml-dialog-footer .alignright")),a.ajax({url:ajaxurl,type:"post",dataType:"json",data:{action:e.action,fields:d.closest(".wcml-dialog-container").find("form").serialize(),icl_nonce:e.nonce},async:!1,success:function(a){e.stay&&(f.remove(),d.removeAttr("disabled"))}})}e.stay||(d.trigger("before_close_dialog"),WCML_Dialog.using_wpdialog?c.wpdialog("close"):c.dialog("close"))})},WCML_Dialog.init=function(){a(document).ready(function(){void 0!==a.wp?WCML_Dialog.using_wpdialog=void 0!==a.wp.wpdialog:WCML_Dialog.using_wpdialog=!1,WCML_Dialog._register_open_handler(),WCML_Dialog._register_close_handler()})},WCML_Dialog.init()});
1
+ var WCML_Dialog=WCML_Dialog||{};jQuery(function(a){var b;WCML_Dialog.dialog=function(c,d){var e=this;"undefined"==typeof c&&(c="generic"),e.overflow_y=a("body").css("overflow-y"),a("body").css("overflow-y","hidden"),b=a("#wcml-dialog-"+c);var f=a("#"+c).attr("title");if("undefined"==typeof f&&(f="undefined"!=d.title?d.title:""),"undefined"==typeof d["class"]&&(d["class"]=""),"undefined"==typeof d.draggable&&(d.draggable=!1),!b.length){a(document.body).append(a('<div class="wcml-dialog-container" title="'+f+'" id="wcml-dialog-'+c+'" />')),b=a("#wcml-dialog-"+c);var g=a(window).height(),h={title:"",autoOpen:!1,show:!0,dialogClass:"wcml-ui-dialog otgs-ui-dialog "+d["class"],position:{my:"center",at:"center",of:window},modal:!0,width:"90%",height:.7*g,resizable:!1,draggable:d.draggable,beforeOpen:function(a){},beforeClose:function(a){},close:function(b){a("body").css("overflow-y",e.overflow_y)},create:function(a){},focus:function(a){},open:function(b){a("body").css("overflow","hidden"),"wcml-cs-dialog"===d["class"]&&WCML_Dialog._attachDialogScrollEvent()},refresh:function(a){}};"undefined"!=typeof d.height&&"wcml-cs-dialog"!=d["class"]&&(h.height=Math.min(.7*g,d.height)),"undefined"!=typeof d.width&&"wcml-cs-dialog"!=d["class"]&&(h.width=d.width),WCML_Dialog.using_wpdialog?b.wpdialog(h):b.dialog(h).on("dialogopen",function(){WCML_Dialog._repositionDialog()})}var i=_.debounce(function(){WCML_Dialog._repositionDialog(),"wcml-cs-dialog"===d["class"]&&WCML_Dialog._attachDialogScrollEvent()},200);if(WCML_Dialog.using_wpdialog?b.wpdialog("open"):b.dialog("open"),d.action){var j=a('<div class="spinner"></div>');j.css({display:"inline-block",visibility:"visible","float":"none"}),b.html(j),a.ajax({url:ajaxurl,type:"post",dataType:"json",data:d,success:function(a){b.html(a.html)}})}return d.content&&a("#"+d.content).length&&b.html(a("#"+d.content).html()),"undefined"!=typeof WCML_Tooltip&&WCML_Tooltip.init(),a(window).resize(i),!1},WCML_Dialog._repositionDialog=function(){var c=a(window).height()-180;b.css("max-height",c),b.dialog("option","position",{my:"center",at:"center",of:window})},WCML_Dialog._attachDialogScrollEvent=function(){var a=b.find(".wcml-currency-preview-wrapper"),c=b.width()>900,d=a.height()+200<b.height();d=d||c&&a.height()<b.height(),d?b.on("scroll.preview",function(){b.find(".wcml-currency-preview-wrapper").css({position:"relative",top:b.scrollTop()})}):b.off("scroll.preview").find(".wcml-currency-preview-wrapper").css({position:"relative",top:0})},WCML_Dialog._register_open_handler=function(){a(document).on("click",".js-wcml-dialog-trigger",function(b){b.preventDefault();var c=!1;a(this).data("dialog")?c=a(this).data("dialog"):a(this).data("action")&&(c=a(this).data("action")),c&&(a(this).data("action")&&a(this).data("action",a(this).data("action").replace(/-/g,"_")),WCML_Dialog.dialog(c,a(this).data()))}),a(document).on("click",".js-wcml-cs-dialog-trigger",function(b){b.preventDefault();var c=!1;a(this).data("dialog")&&(c=a(this).data("dialog"));var d=a(this).data();d["class"]="wcml-cs-dialog",d.draggable=!0,c&&(WCML_Dialog.dialog(c,d),WCML_Currency_Switcher_Settings.initColorPicker(),WCML_Currency_Switcher_Settings.currency_switcher_preview(a("#wcml-dialog-"+c)))})},WCML_Dialog._register_close_handler=function(){a(document).on("click",".wcml-dialog-close-button",function(b){b.preventDefault(),"undefined"!=typeof tinyMCE&&tinyMCE.triggerSave(),a(".wcml-dialog").find(".mce_editor textarea").each(function(){var b=a(this).attr("id"),c=a(this);if(b in tinyMCE.editors){var d=tinyMCE.get(b);d.isHidden()||c.val(d.getContent())}});var c=a(this).closest(".wcml-dialog-container"),d=a(this);d.attr("disabled","disabled");var e=a(this).data();if(e.action){var f=a('<div class="spinner"></div>');f.css({visibility:"visible","float":"right"}).prependTo(a(".wcml-dialog-footer .alignright")),a.ajax({url:ajaxurl,type:"post",dataType:"json",data:{action:e.action,fields:d.closest(".wcml-dialog-container").find("form").serialize(),icl_nonce:e.nonce},async:!1,success:function(a){e.stay&&(f.remove(),d.removeAttr("disabled"))}})}e.stay||(d.trigger("before_close_dialog"),WCML_Dialog.using_wpdialog?c.wpdialog("close"):c.dialog("close"))})},WCML_Dialog.init=function(){a(document).ready(function(){"undefined"!=typeof a.wp?WCML_Dialog.using_wpdialog="undefined"!=typeof a.wp.wpdialog:WCML_Dialog.using_wpdialog=!1,WCML_Dialog._register_open_handler(),WCML_Dialog._register_close_handler()})},WCML_Dialog.init()});
res/js/troubleshooting.js CHANGED
@@ -1,223 +1,232 @@
1
- jQuery(document).ready(function(){
2
- //troubleshooting page
3
- jQuery('#wcml_trbl').on('click',function(){
4
- var field = jQuery(this);
5
- field.attr('disabled', 'disabled');
6
- jQuery('.spinner').css('display','inline-block').css('visibility','visible');
7
-
8
- if(jQuery('#wcml_sync_update_product_count').is(':checked')){
9
- update_product_count();
10
- }else if(jQuery('#wcml_sync_product_variations').is(':checked')){
11
- sync_variations();
12
- }else if(jQuery('#wcml_sync_gallery_images').is(':checked')){
13
- sync_product_gallery();
14
- }else if(jQuery('#wcml_sync_categories').is(':checked')){
15
- sync_product_categories();
16
- }else if(jQuery('#wcml_duplicate_terms').is(':checked')){
17
- duplicate_terms();
18
- }
19
- });
20
 
21
- jQuery('#attr_to_duplicate').on('change',function(){
22
- jQuery('.attr_status').html(jQuery(this).find('option:selected').attr('rel'))
23
- jQuery('#count_terms').val(jQuery(this).find('option:selected').attr('rel'))
24
- });
25
 
26
- jQuery('#wcml_product_type_trbl').on('click',function(){
27
- var field = jQuery(this);
28
- field.attr('disabled', 'disabled');
29
- jQuery('.product_type_spinner').css('display','inline-block').css('visibility','visible');
30
 
31
- fix_product_type_terms();
32
- });
33
 
34
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
 
36
- function update_product_count(){
37
- jQuery.ajax({
38
- type : "post",
39
- url : ajaxurl,
40
- data : {
41
- action: "trbl_update_count",
42
- wcml_nonce: jQuery('#trbl_update_count_nonce').val()
 
43
  },
44
- success: function(response) {
45
- jQuery('.var_status').each(function(){
46
- jQuery(this).html(response);
47
- })
48
- jQuery('#count_prod_variat').val(response);
49
- if(jQuery('#wcml_sync_product_variations').is(':checked')){
50
- sync_variations();
51
- }else if(jQuery('#wcml_sync_gallery_images').is(':checked')){
52
- sync_product_gallery();
53
- }else if(jQuery('#wcml_sync_categories').is(':checked')){
54
- sync_product_categories();
55
- }else if(jQuery('#wcml_duplicate_terms').is(':checked')){
56
- duplicate_terms();
57
- }else{
58
- jQuery('#wcml_trbl').removeAttr('disabled');
59
- jQuery('.spinner').hide();
60
- jQuery('#wcml_trbl').next().fadeOut();
61
- }
62
- }
63
- });
64
- }
65
-
66
- function sync_variations(){
67
- jQuery.ajax({
68
- type : "post",
69
- url : ajaxurl,
70
- data : {
71
- action: "trbl_sync_variations",
72
- wcml_nonce: jQuery('#trbl_sync_variations_nonce').val()
73
  },
74
- success: function(response) {
75
- if(jQuery('#count_prod_variat').val() == 0){
76
- jQuery('.var_status').each(function(){
77
- jQuery(this).html(0);
78
- });
79
- if(jQuery('#wcml_sync_gallery_images').is(':checked')){
80
- sync_product_gallery();
81
- }else if(jQuery('#wcml_sync_categories').is(':checked')){
82
- sync_product_categories();
83
- }else if(jQuery('#wcml_duplicate_terms').is(':checked')){
84
- duplicate_terms();
85
- }else{
86
- jQuery('#wcml_trbl').removeAttr('disabled');
87
- jQuery('.spinner').hide();
88
- jQuery('#wcml_trbl').next().fadeOut();
 
 
 
 
 
 
 
 
 
 
 
 
89
  }
 
 
90
 
91
- }else{
92
- var left = jQuery('#count_prod_variat').val()-3;
93
- if(left < 0 ){
94
- left = 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
  }
96
- jQuery('.var_status').each(function(){
97
- jQuery(this).html(left);
98
- });
99
- jQuery('#count_prod_variat').val(left);
100
- sync_variations();
101
- }
102
- }
103
- });
104
- }
105
-
106
- function sync_product_gallery(){
107
- jQuery.ajax({
108
- type : "post",
109
- url : ajaxurl,
110
- data : {
111
- action: "trbl_gallery_images",
112
- wcml_nonce: jQuery('#trbl_gallery_images_nonce').val(),
113
- page: jQuery('#sync_galerry_page').val()
114
  },
115
- success: function(response) {
116
- if(jQuery('#count_prod').val() == 0){
117
- if(jQuery('#wcml_sync_categories').is(':checked')){
118
- sync_product_categories();
119
- }else if(jQuery('#wcml_duplicate_terms').is(':checked')){
120
- duplicate_terms();
121
- }else{
122
- jQuery('#wcml_trbl').removeAttr('disabled');
123
- jQuery('.spinner').hide();
124
- jQuery('#wcml_trbl').next().fadeOut();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
  }
126
- jQuery('.gallery_status').html(0);
127
- }else{
128
- var left = jQuery('#count_prod').val()-5;
129
- if(left < 0 ){
130
- left = 0;
131
- }else{
132
- jQuery('#sync_galerry_page').val(parseInt(jQuery('#sync_galerry_page').val())+1)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
  }
134
- jQuery('.gallery_status').html(left);
135
- jQuery('#count_prod').val(left);
136
- sync_product_gallery();
137
- }
138
- }
139
- });
140
- }
141
-
142
- function sync_product_categories(){
143
- jQuery.ajax({
144
- type : "post",
145
- url : ajaxurl,
146
- data : {
147
- action: "trbl_sync_categories",
148
- wcml_nonce: jQuery('#trbl_sync_categories_nonce').val(),
149
- page: jQuery('#sync_category_page').val()
150
  },
151
- success: function(response) {
152
- if(jQuery('#count_categories').val() == 0){
153
- if(jQuery('#wcml_duplicate_terms').is(':checked')){
154
- duplicate_terms();
155
- }else{
156
- jQuery('#wcml_trbl').removeAttr('disabled');
157
- jQuery('.spinner').hide();
158
- jQuery('#wcml_trbl').next().fadeOut();
 
 
 
 
 
 
159
  }
160
- jQuery('.cat_status').html(0);
161
- }else{
162
- var left = jQuery('#count_categories').val()-5;
163
- if(left < 0 ){
164
- left = 0;
165
- }else{
166
- jQuery('#sync_category_page').val(parseInt(jQuery('#sync_category_page').val())+1)
 
 
 
 
 
 
 
 
 
 
 
 
 
167
  }
168
- jQuery('.cat_status').html(left);
169
- jQuery('#count_categories').val(left);
170
- sync_product_categories();
171
- }
172
- }
173
- });
174
- }
175
-
176
- function duplicate_terms(){
177
- jQuery.ajax({
178
- type : "post",
179
- url : ajaxurl,
180
- data : {
181
- action: "trbl_duplicate_terms",
182
- wcml_nonce: jQuery('#trbl_duplicate_terms_nonce').val(),
183
- attr: jQuery('#attr_to_duplicate option:selected').val()
184
  },
185
- success: function(response) {
186
- if(jQuery('#count_terms').val() == 0){
 
 
 
 
 
 
 
 
 
 
 
187
  jQuery('#wcml_trbl').removeAttr('disabled');
188
  jQuery('.spinner').hide();
189
  jQuery('#wcml_trbl').next().fadeOut();
190
- jQuery('.attr_status').html(0);
191
- }else{
192
- var left = jQuery('#count_terms').val()-5;
193
- if(left < 0 ){
194
- left = 0;
195
- }
196
- jQuery('.attr_status').html(left);
197
- jQuery('#count_terms').val(left);
198
-
199
- duplicate_terms();
200
  }
201
  }
202
- });
203
- }
204
-
205
- function fix_product_type_terms(){
206
- jQuery.ajax({
207
- type : "post",
208
- url : ajaxurl,
209
- data : {
210
- action: "trbl_fix_product_type_terms",
211
- wcml_nonce: jQuery('#trbl_product_type_terms_nonce').val()
212
- },
213
- success: function(response) {
214
- jQuery('#wcml_product_type_trbl').removeAttr('disabled');
215
- jQuery('.product_type_spinner').hide();
216
- jQuery('.product_type_fix_done').show();
217
- setTimeout(function() {
218
- jQuery('.product_type_fix_done').fadeOut( 300 );
219
- }, 2000);
220
 
221
- }
222
- });
223
- }
 
 
 
 
1
+ jQuery( function($) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
+ WCML_Troubleshooting = {
 
 
 
4
 
 
 
 
 
5
 
6
+ init: function(){
 
7
 
8
+ $(document).ready( function(){
9
+
10
+ //troubleshooting page
11
+ jQuery('#wcml_trbl').on('click',function(){
12
+ var field = jQuery(this);
13
+ field.attr('disabled', 'disabled');
14
+ jQuery('.spinner').css('display','inline-block').css('visibility','visible');
15
+ if(jQuery('#wcml_sync_update_product_count').is(':checked')){
16
+ WCML_Troubleshooting.update_product_count();
17
+ }else{
18
+ WCML_Troubleshooting.run_next_troubleshooting_action();
19
+ }
20
+ });
21
+
22
+ jQuery('#attr_to_duplicate').on('change',function(){
23
+ jQuery('.attr_status').html(jQuery(this).find('option:selected').attr('rel'))
24
+ jQuery('#count_terms').val(jQuery(this).find('option:selected').attr('rel'))
25
+ });
26
 
27
+ jQuery('#wcml_product_type_trbl').on('click',function(){
28
+ var field = jQuery(this);
29
+ field.attr('disabled', 'disabled');
30
+ jQuery('.product_type_spinner').css('display','inline-block').css('visibility','visible');
31
+
32
+ WCML_Troubleshooting.fix_product_type_terms();
33
+ });
34
+ });
35
  },
36
+ update_product_count: function(){
37
+ jQuery.ajax({
38
+ type : "post",
39
+ url : ajaxurl,
40
+ data : {
41
+ action: "trbl_update_count",
42
+ wcml_nonce: jQuery('#trbl_update_count_nonce').val()
43
+ },
44
+ dataType: 'json',
45
+ success: function( response ) {
46
+ jQuery('.var_status').each(function(){
47
+ jQuery(this).html(response.data.count);
48
+ })
49
+ jQuery('#count_prod_variat').val(response.data.count);
50
+ WCML_Troubleshooting.run_next_troubleshooting_action();
51
+ }
52
+ });
 
 
 
 
 
 
 
 
 
 
 
 
53
  },
54
+
55
+ sync_variations: function(){
56
+ jQuery.ajax({
57
+ type : "post",
58
+ url : ajaxurl,
59
+ data : {
60
+ action: "trbl_sync_variations",
61
+ wcml_nonce: jQuery('#trbl_sync_variations_nonce').val()
62
+ },
63
+ dataType: 'json',
64
+ success: function(response) {
65
+ if(jQuery('#count_prod_variat').val() == 0){
66
+ jQuery('.var_status').each(function(){
67
+ jQuery(this).html(0);
68
+ });
69
+ WCML_Troubleshooting.run_next_troubleshooting_action();
70
+ }else{
71
+ var left = jQuery('#count_prod_variat').val()-3;
72
+ if(left < 0 ){
73
+ left = 0;
74
+ }
75
+ jQuery('.var_status').each(function(){
76
+ jQuery(this).html(left);
77
+ });
78
+ jQuery('#count_prod_variat').val(left);
79
+ WCML_Troubleshooting.sync_variations();
80
+ }
81
  }
82
+ });
83
+ },
84
 
85
+ sync_product_gallery: function(){
86
+ jQuery.ajax({
87
+ type : "post",
88
+ url : ajaxurl,
89
+ data : {
90
+ action: "trbl_gallery_images",
91
+ wcml_nonce: jQuery('#trbl_gallery_images_nonce').val(),
92
+ page: jQuery('#sync_galerry_page').val()
93
+ },
94
+ dataType: 'json',
95
+ success: function(response) {
96
+ if(jQuery('#count_galleries').val() == 0){
97
+ WCML_Troubleshooting.run_next_troubleshooting_action();
98
+ jQuery('.gallery_status').html(0);
99
+ }else{
100
+ var left = jQuery('#count_galleries').val()-5;
101
+ if(left < 0 ){
102
+ left = 0;
103
+ }else{
104
+ jQuery('#sync_galerry_page').val(parseInt(jQuery('#sync_galerry_page').val())+1)
105
+ }
106
+ jQuery('.gallery_status').html(left);
107
+ jQuery('#count_galleries').val(left);
108
+ WCML_Troubleshooting.sync_product_gallery();
109
+ }
110
  }
111
+ });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  },
113
+
114
+ sync_product_categories: function(){
115
+ jQuery.ajax({
116
+ type : "post",
117
+ url : ajaxurl,
118
+ data : {
119
+ action: "trbl_sync_categories",
120
+ wcml_nonce: jQuery('#trbl_sync_categories_nonce').val(),
121
+ page: jQuery('#sync_category_page').val()
122
+ },
123
+ success: function(response) {
124
+ if(jQuery('#count_categories').val() == 0){
125
+ WCML_Troubleshooting.run_next_troubleshooting_action();
126
+ jQuery('.cat_status').html(0);
127
+ }else{
128
+ var left = jQuery('#count_categories').val()-5;
129
+ if(left < 0 ){
130
+ left = 0;
131
+ }else{
132
+ jQuery('#sync_category_page').val(parseInt(jQuery('#sync_category_page').val())+1)
133
+ }
134
+ jQuery('.cat_status').html(left);
135
+ jQuery('#count_categories').val(left);
136
+ WCML_Troubleshooting.sync_product_categories();
137
+ }
138
  }
139
+ });
140
+ },
141
+
142
+ duplicate_terms: function(){
143
+ jQuery.ajax({
144
+ type : "post",
145
+ url : ajaxurl,
146
+ data : {
147
+ action: "trbl_duplicate_terms",
148
+ wcml_nonce: jQuery('#trbl_duplicate_terms_nonce').val(),
149
+ attr: jQuery('#attr_to_duplicate option:selected').val()
150
+ },
151
+ dataType: 'json',
152
+ success: function(response) {
153
+ if(jQuery('#count_terms').val() == 0){
154
+ WCML_Troubleshooting.run_next_troubleshooting_action();
155
+ jQuery('.attr_status').html(0);
156
+ }else{
157
+ var left = jQuery('#count_terms').val()-5;
158
+ if(left < 0 ){
159
+ left = 0;
160
+ }
161
+ jQuery('.attr_status').html(left);
162
+ jQuery('#count_terms').val(left);
163
+
164
+ WCML_Troubleshooting.duplicate_terms();
165
+ }
166
  }
167
+ });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
168
  },
169
+
170
+ sync_stock: function(){
171
+ jQuery.ajax({
172
+ type : "post",
173
+ url : ajaxurl,
174
+ data : {
175
+ action: "trbl_sync_stock",
176
+ wcml_nonce: jQuery('#trbl_sync_stock_nonce').val()
177
+ },
178
+ dataType: 'json',
179
+ success: function(response) {
180
+ jQuery('#count_stock').val(0);
181
+ WCML_Troubleshooting.run_next_troubleshooting_action();
182
+ jQuery('.stock_status').html(0);
183
  }
184
+ });
185
+ },
186
+
187
+ fix_product_type_terms: function(){
188
+ jQuery.ajax({
189
+ type : "post",
190
+ url : ajaxurl,
191
+ data : {
192
+ action: "trbl_fix_product_type_terms",
193
+ wcml_nonce: jQuery('#trbl_product_type_terms_nonce').val()
194
+ },
195
+ dataType: 'json',
196
+ success: function(response) {
197
+ jQuery('#wcml_product_type_trbl').removeAttr('disabled');
198
+ jQuery('.product_type_spinner').hide();
199
+ jQuery('.product_type_fix_done').show();
200
+ setTimeout(function() {
201
+ jQuery('.product_type_fix_done').fadeOut( 300 );
202
+ }, 2000);
203
+
204
  }
205
+ });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
206
  },
207
+
208
+ run_next_troubleshooting_action: function(){
209
+ if(jQuery('#wcml_sync_product_variations').is(':checked') && parseInt( jQuery('#count_prod_variat').val() ) !== 0 ){
210
+ WCML_Troubleshooting.sync_variations();
211
+ }else if(jQuery('#wcml_sync_gallery_images').is(':checked') && parseInt( jQuery('#count_galleries').val() ) !== 0 ){
212
+ WCML_Troubleshooting.sync_product_gallery();
213
+ }else if(jQuery('#wcml_sync_categories').is(':checked') && parseInt( jQuery('#count_categories').val() ) !== 0 ){
214
+ WCML_Troubleshooting.sync_product_categories();
215
+ }else if(jQuery('#wcml_duplicate_terms').is(':checked') && parseInt( jQuery('#count_terms').val() ) !== 0 ){
216
+ WCML_Troubleshooting.duplicate_terms();
217
+ }else if(jQuery('#wcml_sync_stock').is(':checked') && parseInt( jQuery('#count_stock').val() ) !== 0 ){
218
+ WCML_Troubleshooting.sync_stock();
219
+ }else{
220
  jQuery('#wcml_trbl').removeAttr('disabled');
221
  jQuery('.spinner').hide();
222
  jQuery('#wcml_trbl').next().fadeOut();
 
 
 
 
 
 
 
 
 
 
223
  }
224
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
225
 
226
+ }
227
+
228
+ WCML_Troubleshooting.init();
229
+
230
+ });
231
+
232
+
res/js/troubleshooting.min.js CHANGED
@@ -1 +1 @@
1
- function update_product_count(){jQuery.ajax({type:"post",url:ajaxurl,data:{action:"trbl_update_count",wcml_nonce:jQuery("#trbl_update_count_nonce").val()},success:function(a){jQuery(".var_status").each(function(){jQuery(this).html(a)}),jQuery("#count_prod_variat").val(a),jQuery("#wcml_sync_product_variations").is(":checked")?sync_variations():jQuery("#wcml_sync_gallery_images").is(":checked")?sync_product_gallery():jQuery("#wcml_sync_categories").is(":checked")?sync_product_categories():jQuery("#wcml_duplicate_terms").is(":checked")?duplicate_terms():(jQuery("#wcml_trbl").removeAttr("disabled"),jQuery(".spinner").hide(),jQuery("#wcml_trbl").next().fadeOut())}})}function sync_variations(){jQuery.ajax({type:"post",url:ajaxurl,data:{action:"trbl_sync_variations",wcml_nonce:jQuery("#trbl_sync_variations_nonce").val()},success:function(a){if(0==jQuery("#count_prod_variat").val())jQuery(".var_status").each(function(){jQuery(this).html(0)}),jQuery("#wcml_sync_gallery_images").is(":checked")?sync_product_gallery():jQuery("#wcml_sync_categories").is(":checked")?sync_product_categories():jQuery("#wcml_duplicate_terms").is(":checked")?duplicate_terms():(jQuery("#wcml_trbl").removeAttr("disabled"),jQuery(".spinner").hide(),jQuery("#wcml_trbl").next().fadeOut());else{var b=jQuery("#count_prod_variat").val()-3;b<0&&(b=0),jQuery(".var_status").each(function(){jQuery(this).html(b)}),jQuery("#count_prod_variat").val(b),sync_variations()}}})}function sync_product_gallery(){jQuery.ajax({type:"post",url:ajaxurl,data:{action:"trbl_gallery_images",wcml_nonce:jQuery("#trbl_gallery_images_nonce").val(),page:jQuery("#sync_galerry_page").val()},success:function(a){if(0==jQuery("#count_prod").val())jQuery("#wcml_sync_categories").is(":checked")?sync_product_categories():jQuery("#wcml_duplicate_terms").is(":checked")?duplicate_terms():(jQuery("#wcml_trbl").removeAttr("disabled"),jQuery(".spinner").hide(),jQuery("#wcml_trbl").next().fadeOut()),jQuery(".gallery_status").html(0);else{var b=jQuery("#count_prod").val()-5;b<0?b=0:jQuery("#sync_galerry_page").val(parseInt(jQuery("#sync_galerry_page").val())+1),jQuery(".gallery_status").html(b),jQuery("#count_prod").val(b),sync_product_gallery()}}})}function sync_product_categories(){jQuery.ajax({type:"post",url:ajaxurl,data:{action:"trbl_sync_categories",wcml_nonce:jQuery("#trbl_sync_categories_nonce").val(),page:jQuery("#sync_category_page").val()},success:function(a){if(0==jQuery("#count_categories").val())jQuery("#wcml_duplicate_terms").is(":checked")?duplicate_terms():(jQuery("#wcml_trbl").removeAttr("disabled"),jQuery(".spinner").hide(),jQuery("#wcml_trbl").next().fadeOut()),jQuery(".cat_status").html(0);else{var b=jQuery("#count_categories").val()-5;b<0?b=0:jQuery("#sync_category_page").val(parseInt(jQuery("#sync_category_page").val())+1),jQuery(".cat_status").html(b),jQuery("#count_categories").val(b),sync_product_categories()}}})}function duplicate_terms(){jQuery.ajax({type:"post",url:ajaxurl,data:{action:"trbl_duplicate_terms",wcml_nonce:jQuery("#trbl_duplicate_terms_nonce").val(),attr:jQuery("#attr_to_duplicate option:selected").val()},success:function(a){if(0==jQuery("#count_terms").val())jQuery("#wcml_trbl").removeAttr("disabled"),jQuery(".spinner").hide(),jQuery("#wcml_trbl").next().fadeOut(),jQuery(".attr_status").html(0);else{var b=jQuery("#count_terms").val()-5;b<0&&(b=0),jQuery(".attr_status").html(b),jQuery("#count_terms").val(b),duplicate_terms()}}})}function fix_product_type_terms(){jQuery.ajax({type:"post",url:ajaxurl,data:{action:"trbl_fix_product_type_terms",wcml_nonce:jQuery("#trbl_product_type_terms_nonce").val()},success:function(a){jQuery("#wcml_product_type_trbl").removeAttr("disabled"),jQuery(".product_type_spinner").hide(),jQuery(".product_type_fix_done").show(),setTimeout(function(){jQuery(".product_type_fix_done").fadeOut(300)},2e3)}})}jQuery(document).ready(function(){jQuery("#wcml_trbl").on("click",function(){jQuery(this).attr("disabled","disabled"),jQuery(".spinner").css("display","inline-block").css("visibility","visible"),jQuery("#wcml_sync_update_product_count").is(":checked")?update_product_count():jQuery("#wcml_sync_product_variations").is(":checked")?sync_variations():jQuery("#wcml_sync_gallery_images").is(":checked")?sync_product_gallery():jQuery("#wcml_sync_categories").is(":checked")?sync_product_categories():jQuery("#wcml_duplicate_terms").is(":checked")&&duplicate_terms()}),jQuery("#attr_to_duplicate").on("change",function(){jQuery(".attr_status").html(jQuery(this).find("option:selected").attr("rel")),jQuery("#count_terms").val(jQuery(this).find("option:selected").attr("rel"))}),jQuery("#wcml_product_type_trbl").on("click",function(){jQuery(this).attr("disabled","disabled"),jQuery(".product_type_spinner").css("display","inline-block").css("visibility","visible"),fix_product_type_terms()})});
1
+ jQuery(function(a){WCML_Troubleshooting={init:function(){a(document).ready(function(){jQuery("#wcml_trbl").on("click",function(){var a=jQuery(this);a.attr("disabled","disabled"),jQuery(".spinner").css("display","inline-block").css("visibility","visible"),jQuery("#wcml_sync_update_product_count").is(":checked")?WCML_Troubleshooting.update_product_count():WCML_Troubleshooting.run_next_troubleshooting_action()}),jQuery("#attr_to_duplicate").on("change",function(){jQuery(".attr_status").html(jQuery(this).find("option:selected").attr("rel")),jQuery("#count_terms").val(jQuery(this).find("option:selected").attr("rel"))}),jQuery("#wcml_product_type_trbl").on("click",function(){var a=jQuery(this);a.attr("disabled","disabled"),jQuery(".product_type_spinner").css("display","inline-block").css("visibility","visible"),WCML_Troubleshooting.fix_product_type_terms()})})},update_product_count:function(){jQuery.ajax({type:"post",url:ajaxurl,data:{action:"trbl_update_count",wcml_nonce:jQuery("#trbl_update_count_nonce").val()},dataType:"json",success:function(a){jQuery(".var_status").each(function(){jQuery(this).html(a.data.count)}),jQuery("#count_prod_variat").val(a.data.count),WCML_Troubleshooting.run_next_troubleshooting_action()}})},sync_variations:function(){jQuery.ajax({type:"post",url:ajaxurl,data:{action:"trbl_sync_variations",wcml_nonce:jQuery("#trbl_sync_variations_nonce").val()},dataType:"json",success:function(a){if(0==jQuery("#count_prod_variat").val())jQuery(".var_status").each(function(){jQuery(this).html(0)}),WCML_Troubleshooting.run_next_troubleshooting_action();else{var b=jQuery("#count_prod_variat").val()-3;0>b&&(b=0),jQuery(".var_status").each(function(){jQuery(this).html(b)}),jQuery("#count_prod_variat").val(b),WCML_Troubleshooting.sync_variations()}}})},sync_product_gallery:function(){jQuery.ajax({type:"post",url:ajaxurl,data:{action:"trbl_gallery_images",wcml_nonce:jQuery("#trbl_gallery_images_nonce").val(),page:jQuery("#sync_galerry_page").val()},dataType:"json",success:function(a){if(0==jQuery("#count_galleries").val())WCML_Troubleshooting.run_next_troubleshooting_action(),jQuery(".gallery_status").html(0);else{var b=jQuery("#count_galleries").val()-5;0>b?b=0:jQuery("#sync_galerry_page").val(parseInt(jQuery("#sync_galerry_page").val())+1),jQuery(".gallery_status").html(b),jQuery("#count_galleries").val(b),WCML_Troubleshooting.sync_product_gallery()}}})},sync_product_categories:function(){jQuery.ajax({type:"post",url:ajaxurl,data:{action:"trbl_sync_categories",wcml_nonce:jQuery("#trbl_sync_categories_nonce").val(),page:jQuery("#sync_category_page").val()},success:function(a){if(0==jQuery("#count_categories").val())WCML_Troubleshooting.run_next_troubleshooting_action(),jQuery(".cat_status").html(0);else{var b=jQuery("#count_categories").val()-5;0>b?b=0:jQuery("#sync_category_page").val(parseInt(jQuery("#sync_category_page").val())+1),jQuery(".cat_status").html(b),jQuery("#count_categories").val(b),WCML_Troubleshooting.sync_product_categories()}}})},duplicate_terms:function(){jQuery.ajax({type:"post",url:ajaxurl,data:{action:"trbl_duplicate_terms",wcml_nonce:jQuery("#trbl_duplicate_terms_nonce").val(),attr:jQuery("#attr_to_duplicate option:selected").val()},dataType:"json",success:function(a){if(0==jQuery("#count_terms").val())WCML_Troubleshooting.run_next_troubleshooting_action(),jQuery(".attr_status").html(0);else{var b=jQuery("#count_terms").val()-5;0>b&&(b=0),jQuery(".attr_status").html(b),jQuery("#count_terms").val(b),WCML_Troubleshooting.duplicate_terms()}}})},sync_stock:function(){jQuery.ajax({type:"post",url:ajaxurl,data:{action:"trbl_sync_stock",wcml_nonce:jQuery("#trbl_sync_stock_nonce").val()},dataType:"json",success:function(a){jQuery("#count_stock").val(0),WCML_Troubleshooting.run_next_troubleshooting_action(),jQuery(".stock_status").html(0)}})},fix_product_type_terms:function(){jQuery.ajax({type:"post",url:ajaxurl,data:{action:"trbl_fix_product_type_terms",wcml_nonce:jQuery("#trbl_product_type_terms_nonce").val()},dataType:"json",success:function(a){jQuery("#wcml_product_type_trbl").removeAttr("disabled"),jQuery(".product_type_spinner").hide(),jQuery(".product_type_fix_done").show(),setTimeout(function(){jQuery(".product_type_fix_done").fadeOut(300)},2e3)}})},run_next_troubleshooting_action:function(){jQuery("#wcml_sync_product_variations").is(":checked")&&0!==parseInt(jQuery("#count_prod_variat").val())?WCML_Troubleshooting.sync_variations():jQuery("#wcml_sync_gallery_images").is(":checked")&&0!==parseInt(jQuery("#count_galleries").val())?WCML_Troubleshooting.sync_product_gallery():jQuery("#wcml_sync_categories").is(":checked")&&0!==parseInt(jQuery("#count_categories").val())?WCML_Troubleshooting.sync_product_categories():jQuery("#wcml_duplicate_terms").is(":checked")&&0!==parseInt(jQuery("#count_terms").val())?WCML_Troubleshooting.duplicate_terms():jQuery("#wcml_sync_stock").is(":checked")&&0!==parseInt(jQuery("#count_stock").val())?WCML_Troubleshooting.sync_stock():(jQuery("#wcml_trbl").removeAttr("disabled"),jQuery(".spinner").hide(),jQuery("#wcml_trbl").next().fadeOut())}},WCML_Troubleshooting.init()});
res/js/wcml-multi-currency.js CHANGED
@@ -30,8 +30,7 @@ function wcml_load_currency( currency, force_switch ){
30
  data : {
31
  action: 'wcml_switch_currency',
32
  currency : currency,
33
- force_switch: force_switch,
34
- wcml_nonce: wcml_mc_settings.wcml_mc_nonce
35
  },
36
  success: function(response) {
37
  if(typeof response.error !== 'undefined') {
30
  data : {
31
  action: 'wcml_switch_currency',
32
  currency : currency,
33
+ force_switch: force_switch
 
34
  },
35
  success: function(response) {
36
  if(typeof response.error !== 'undefined') {
res/js/wcml-multi-currency.min.js CHANGED
@@ -1 +1 @@
1
- function wcml_load_currency(a,b){var c=jQuery('<img style="margin-left:10px;" width="16" heigth="16" src="'+wcml_mc_settings.wcml_spinner+'" />');jQuery(".wcml_currency_switcher").after(),c.insertAfter(jQuery(".wcml_currency_switcher")),void 0===b&&(b=0),jQuery.ajax({type:"post",url:woocommerce_params.ajax_url,dataType:"json",data:{action:"wcml_switch_currency",currency:a,force_switch:b,wcml_nonce:wcml_mc_settings.wcml_mc_nonce},success:function(b){if(void 0!==b.error)alert(b.error);else if(void 0!==b.prevent_switching)jQuery("body").append(b.prevent_switching);else{if(void 0!==wcml_mc_settings.w3tc){var c=window.location.href;c=c.replace(/&wcmlc(\=[^&]*)?(?=&|$)|wcmlc(\=[^&]*)?(&|$)/,""),c=c.replace(/\?$/,"");var d=c.indexOf("?")!=-1?"&":"?",e=c+d+"wcmlc="+a}else var e=window.location.href;window.location=e}}})}jQuery(document).ready(function(){jQuery(document).on("click",".wcml_currency_switcher a",function(a){if(a.preventDefault(),jQuery(this).is(":disabled")||jQuery(this).parent().hasClass("wcml-cs-active-currency")||jQuery(this).hasClass("wcml-cs-active-currency"))return!1;jQuery(this).off(a),wcml_load_currency(jQuery(this).attr("rel"))}),"undefined"!=typeof woocommerce_price_slider_params&&(woocommerce_price_slider_params.currency_symbol=wcml_mc_settings.current_currency.symbol)});
1
+ function wcml_load_currency(a,b){var c=jQuery('<img style="margin-left:10px;" width="16" heigth="16" src="'+wcml_mc_settings.wcml_spinner+'" />');jQuery(".wcml_currency_switcher").after(),c.insertAfter(jQuery(".wcml_currency_switcher")),"undefined"==typeof b&&(b=0),jQuery.ajax({type:"post",url:woocommerce_params.ajax_url,dataType:"json",data:{action:"wcml_switch_currency",currency:a,force_switch:b},success:function(b){if("undefined"!=typeof b.error)alert(b.error);else if("undefined"!=typeof b.prevent_switching)jQuery("body").append(b.prevent_switching);else{if("undefined"!=typeof wcml_mc_settings.w3tc){var c=window.location.href;c=c.replace(/&wcmlc(\=[^&]*)?(?=&|$)|wcmlc(\=[^&]*)?(&|$)/,""),c=c.replace(/\?$/,"");var d=-1!=c.indexOf("?")?"&":"?",e=c+d+"wcmlc="+a}else var e=window.location.href;window.location=e}}})}jQuery(document).ready(function(){jQuery(document).on("click",".wcml_currency_switcher a",function(a){return a.preventDefault(),jQuery(this).is(":disabled")||jQuery(this).parent().hasClass("wcml-cs-active-currency")||jQuery(this).hasClass("wcml-cs-active-currency")?!1:(jQuery(this).off(a),void wcml_load_currency(jQuery(this).attr("rel")))}),"undefined"!=typeof woocommerce_price_slider_params&&(woocommerce_price_slider_params.currency_symbol=wcml_mc_settings.current_currency.symbol)});
templates/plugins-wrap.twig CHANGED
@@ -2,10 +2,10 @@
2
  <h1>{{ strings.title }}</h1>
3
 
4
  <nav class="wcml-tabs wpml-tabs" style="display:table;margin-top:30px;">
5
- <a class="nav-tab nav-tab-active" href="{{ link_url|e }}" >{{ strings.required }}</a>
6
  </nav>
7
 
8
- <div class="wcml-wrap">
9
  <div class="wcml-section">
10
  <div class="wcml-section-header">
11
  <h3>
@@ -18,30 +18,30 @@
18
  <ul>
19
  {% if old_wpml %}
20
  <li>
21
- <i class="otgs-ico-warning"></i>
22
  {{ strings.old_wpml_link|raw }}
23
  <a href="{{ tracking_link }}"
24
  target="_blank">{{ strings.update_wpml }}</a>
25
  </li>
26
  {% elseif icl_version %}
27
  <li>
28
- <i class="otgs-ico-ok"></i>
29
  {{ strings.inst_active|format( strings.wpml )|raw }}
30
  </li>
31
  {% if icl_setup %}
32
  <li>
33
- <i class="otgs-ico-ok"></i>
34
  {{ strings.is_setup|format( strings.wpml )|raw }}
35
  </li>
36
  {% else %}
37
  <li>
38
- <i class="otgs-ico-warning"></i>
39
  {{ strings.not_setup|format( strings.wpml )|raw }}
40
  </li>
41
  {% endif %}
42
  {% else %}
43
  <li>
44
- <i class="otgs-ico-warning"></i>
45
  {{ strings.wpml_not_inst|raw }}
46
  <a href="{{ install_wpml_link|e }}" target="_blank">{{ strings.get_wpml }}</a>
47
  </li>
@@ -49,12 +49,12 @@
49
 
50
  {% if media_version %}
51
  <li>
52
- <i class="otgs-ico-ok"></i>
53
  {{ strings.inst_active|format( strings.media )|raw }}
54
  </li>
55
  {% else %}
56
  <li>
57
- <i class="otgs-ico-warning"></i>
58
  {{ strings.not_inst|format( strings.media )|raw }}
59
  <a href="{{ install_wpml_link|e }}" target="_blank">{{ strings.get_wpml_media }}</a>
60
  </li>
@@ -62,12 +62,12 @@
62
 
63
  {% if tm_version %}
64
  <li>
65
- <i class="otgs-ico-ok"></i>
66
  {{ strings.inst_active|format( strings.tm )|raw }}
67
  </li>
68
  {% else %}
69
  <li>
70
- <i class="otgs-ico-warning"></i>
71
  {{ strings.not_inst|format( strings.tm )|raw }}
72
  <a href="{{ install_wpml_link|e }}" target="_blank">{{ strings.get_wpml_tm }}</a>
73
  </li>
@@ -75,12 +75,12 @@
75
 
76
  {% if st_version %}
77
  <li>
78
- <i class="otgs-ico-ok"></i>
79
  {{ strings.inst_active|format( strings.st )|raw }}
80
  </li>
81
  {% else %}
82
  <li>
83
- <i class="otgs-ico-warning"></i>
84
  {{ strings.not_inst|format( strings.st )|raw }}
85
  <a href="{{ install_wpml_link|e }}" target="_blank">{{ strings.get_wpml_st }}</a>
86
  </li>
@@ -88,18 +88,18 @@
88
 
89
  {% if old_wc %}
90
  <li>
91
- <i class="otgs-ico-warning"></i>
92
  {{ strings.old_wc|raw }}
93
  <a href="{{ wc_link|e }}" target="_blank">{{ strings.download_wc }}</a>
94
  </li>
95
  {% elseif wc %}
96
  <li>
97
- <i class="otgs-ico-ok"></i>
98
  {{ strings.inst_active|format( strings.wc )|raw }}
99
  </li>
100
  {% else %}
101
  <li>
102
- <i class="otgs-ico-warning"></i>
103
  {{ strings.not_inst|format( strings.wc )|raw }}
104
  <a href="{{ wc_link|e }}" target="_blank">{{ strings.download_wc }}</a>
105
  </li>
2
  <h1>{{ strings.title }}</h1>
3
 
4
  <nav class="wcml-tabs wpml-tabs" style="display:table;margin-top:30px;">
5
+ <a class="nav-tab nav-tab-active wcml-required-plugins-tab" href="{{ link_url|e }}" >{{ strings.required }}</a>
6
  </nav>
7
 
8
+ <div class="wcml-wrap wcml-required-plugins-wrap">
9
  <div class="wcml-section">
10
  <div class="wcml-section-header">
11
  <h3>
18
  <ul>
19
  {% if old_wpml %}
20
  <li>
21
+ <i class="otgs-ico-warning wpml-multilingual-cms"></i>
22
  {{ strings.old_wpml_link|raw }}
23
  <a href="{{ tracking_link }}"
24
  target="_blank">{{ strings.update_wpml }}</a>
25
  </li>
26
  {% elseif icl_version %}
27
  <li>
28
+ <i class="otgs-ico-ok wpml-multilingual-cms"></i>
29
  {{ strings.inst_active|format( strings.wpml )|raw }}
30
  </li>
31
  {% if icl_setup %}
32
  <li>
33
+ <i class="otgs-ico-ok wpml-multilingual-cms wpml-setup"></i>
34
  {{ strings.is_setup|format( strings.wpml )|raw }}
35
  </li>
36
  {% else %}
37
  <li>
38
+ <i class="otgs-ico-warning wpml-multilingual-cms wpml-setup"></i>
39
  {{ strings.not_setup|format( strings.wpml )|raw }}
40
  </li>
41
  {% endif %}
42
  {% else %}
43
  <li>
44
+ <i class="otgs-ico-warning wpml-multilingual-cms"></i>
45
  {{ strings.wpml_not_inst|raw }}
46
  <a href="{{ install_wpml_link|e }}" target="_blank">{{ strings.get_wpml }}</a>
47
  </li>
49
 
50
  {% if media_version %}
51
  <li>
52
+ <i class="otgs-ico-ok wpml-media"></i>
53
  {{ strings.inst_active|format( strings.media )|raw }}
54
  </li>
55
  {% else %}
56
  <li>
57
+ <i class="otgs-ico-warning wpml-media"></i>
58
  {{ strings.not_inst|format( strings.media )|raw }}
59
  <a href="{{ install_wpml_link|e }}" target="_blank">{{ strings.get_wpml_media }}</a>
60
  </li>
62
 
63
  {% if tm_version %}
64
  <li>
65
+ <i class="otgs-ico-ok wpml-translation-management"></i>
66
  {{ strings.inst_active|format( strings.tm )|raw }}
67
  </li>
68
  {% else %}
69
  <li>
70
+ <i class="otgs-ico-warning wpml-translation-management"></i>
71
  {{ strings.not_inst|format( strings.tm )|raw }}
72
  <a href="{{ install_wpml_link|e }}" target="_blank">{{ strings.get_wpml_tm }}</a>
73
  </li>
75
 
76
  {% if st_version %}
77
  <li>
78
+ <i class="otgs-ico-ok wpml-string-translation"></i>
79
  {{ strings.inst_active|format( strings.st )|raw }}
80
  </li>
81
  {% else %}
82
  <li>
83
+ <i class="otgs-ico-warning wpml-string-translation"></i>
84
  {{ strings.not_inst|format( strings.st )|raw }}
85
  <a href="{{ install_wpml_link|e }}" target="_blank">{{ strings.get_wpml_st }}</a>
86
  </li>
88
 
89
  {% if old_wc %}
90
  <li>
91
+ <i class="otgs-ico-warning woocommerce"></i>
92
  {{ strings.old_wc|raw }}
93
  <a href="{{ wc_link|e }}" target="_blank">{{ strings.download_wc }}</a>
94
  </li>
95
  {% elseif wc %}
96
  <li>
97
+ <i class="otgs-ico-ok woocommerce"></i>
98
  {{ strings.inst_active|format( strings.wc )|raw }}
99
  </li>
100
  {% else %}
101
  <li>
102
+ <i class="otgs-ico-warning woocommerce"></i>
103
  {{ strings.not_inst|format( strings.wc )|raw }}
104
  <a href="{{ wc_link|e }}" target="_blank">{{ strings.download_wc }}</a>
105
  </li>
templates/troubleshooting.twig CHANGED
@@ -51,8 +51,9 @@
51
  <option value="0" >{{ strings.none }}</option>
52
  {% endif %}
53
 
 
54
  {% for tax in all_products_taxonomies %}
55
- {% if loop.index == 0 %}
56
  {% set terms_count = tax.terms_count %}
57
  {% endif %}
58
 
@@ -66,12 +67,22 @@
66
  </label>
67
 
68
  </li>
 
 
 
 
 
 
 
 
69
  <li>
70
  <button type="button" class="button-secondary" id="wcml_trbl">{{ strings.start }}</button>
71
  <input id="count_prod_variat" type="hidden" value="{{ prod_with_variations }}"/>
72
  <input id="count_prod" type="hidden" value="{{ prod_count }}"/>
 
73
  <input id="count_categories" type="hidden" value="{{ prod_categories_count }}"/>
74
  <input id="count_terms" type="hidden" value="<{{ terms_count }}"/>
 
75
  <input id="sync_galerry_page" type="hidden" value="0"/>
76
  <input id="sync_category_page" type="hidden" value="0"/>
77
  <span class="spinner"></span>
@@ -80,6 +91,7 @@
80
  {{ nonces.trbl_gallery_images|raw }}
81
  {{ nonces.trbl_sync_categories|raw }}
82
  {{ nonces.trbl_duplicate_terms|raw }}
 
83
  </li>
84
  </ul>
85
  {% if product_type_sync_needed %}
51
  <option value="0" >{{ strings.none }}</option>
52
  {% endif %}
53
 
54
+ {% set terms_count = 0 %}
55
  {% for tax in all_products_taxonomies %}
56
+ {% if loop.first %}
57
  {% set terms_count = tax.terms_count %}
58
  {% endif %}
59
 
67
  </label>
68
 
69
  </li>
70
+ <li>
71
+ <label>
72
+ <input type="checkbox" id="wcml_sync_stock" />
73
+ {{ strings.sync_stock }}
74
+ <span class="stock_status">{{ sync_stock_count }}</span>
75
+ <span>{{ strings.left }}</span>
76
+ </label>
77
+ </li>
78
  <li>
79
  <button type="button" class="button-secondary" id="wcml_trbl">{{ strings.start }}</button>
80
  <input id="count_prod_variat" type="hidden" value="{{ prod_with_variations }}"/>
81
  <input id="count_prod" type="hidden" value="{{ prod_count }}"/>
82
+ <input id="count_galleries" type="hidden" value="{{ prod_count }}"/>
83
  <input id="count_categories" type="hidden" value="{{ prod_categories_count }}"/>
84
  <input id="count_terms" type="hidden" value="<{{ terms_count }}"/>
85
+ <input id="count_stock" type="hidden" value="<{{ sync_stock_count }}"/>
86
  <input id="sync_galerry_page" type="hidden" value="0"/>
87
  <input id="sync_category_page" type="hidden" value="0"/>
88
  <span class="spinner"></span>
91
  {{ nonces.trbl_gallery_images|raw }}
92
  {{ nonces.trbl_sync_categories|raw }}
93
  {{ nonces.trbl_duplicate_terms|raw }}
94
+ {{ nonces.trbl_sync_stock|raw }}
95
  </li>
96
  </ul>
97
  {% if product_type_sync_needed %}
vendor/autoload.php CHANGED
@@ -4,4 +4,4 @@
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
- return ComposerAutoloaderInitb607dde9b5d8295faf917ebd1312c1e1::getLoader();
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
+ return ComposerAutoloaderInitb9ffed287a5b4e2fcc802a91254f114a::getLoader();
vendor/autoload_52.php CHANGED
@@ -4,4 +4,4 @@
4
 
5
  require_once dirname(__FILE__) . '/composer'.'/autoload_real_52.php';
6
 
7
- return ComposerAutoloaderInit88b7ad9735ac37cb213cb9c6587b3e8d::getLoader();
4
 
5
  require_once dirname(__FILE__) . '/composer'.'/autoload_real_52.php';
6
 
7
+ return ComposerAutoloaderInit38be79df74f6b23b0833390c6a01eb02::getLoader();
vendor/composer/ClassLoader.php CHANGED
@@ -374,9 +374,13 @@ class ClassLoader
374
 
375
  $first = $class[0];
376
  if (isset($this->prefixLengthsPsr4[$first])) {
377
- foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) {
378
- if (0 === strpos($class, $prefix)) {
379
- foreach ($this->prefixDirsPsr4[$prefix] as $dir) {
 
 
 
 
380
  if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
381
  return $file;
382
  }
374
 
375
  $first = $class[0];
376
  if (isset($this->prefixLengthsPsr4[$first])) {
377
+ $subPath = $class;
378
+ while (false !== $lastPos = strrpos($subPath, '\\')) {
379
+ $subPath = substr($subPath, 0, $lastPos);
380
+ $search = $subPath.'\\';
381
+ if (isset($this->prefixDirsPsr4[$search])) {
382
+ foreach ($this->prefixDirsPsr4[$search] as $dir) {
383
+ $length = $this->prefixLengthsPsr4[$first][$search];
384
  if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
385
  return $file;
386
  }
vendor/composer/LICENSE CHANGED
@@ -1,5 +1,5 @@
1
 
2
- Copyright (c) 2016 Nils Adermann, Jordi Boggiano
3
 
4
  Permission is hereby granted, free of charge, to any person obtaining a copy
5
  of this software and associated documentation files (the "Software"), to deal
1
 
2
+ Copyright (c) Nils Adermann, Jordi Boggiano
3
 
4
  Permission is hereby granted, free of charge, to any person obtaining a copy
5
  of this software and associated documentation files (the "Software"), to deal
vendor/composer/autoload_classmap.php CHANGED
@@ -328,6 +328,7 @@ return array(
328
  'WCML_Flatsome' => $baseDir . '/compatibility/class-wcml-flatsome.php',
329
  'WCML_Install' => $baseDir . '/inc/class-wcml-install.php',
330
  'WCML_JCK_WSSV' => $baseDir . '/compatibility/class-wcml-jck-wssv.php',
 
331
  'WCML_Languages_Upgrade_Notice' => $baseDir . '/inc/template-classes/class-wcml-languages-upgrade-notice.php',
332
  'WCML_Languages_Upgrader' => $baseDir . '/inc/class-wcml-languages-upgrader.php',
333
  'WCML_Links' => $baseDir . '/inc/admin-menus/class-wcml-links.php',
@@ -349,6 +350,7 @@ return array(
349
  'WCML_Multi_Currency_UI' => $baseDir . '/inc/template-classes/multi-currency/class-wcml-multi-currency-ui.php',
350
  'WCML_Not_Translatable_Attributes' => $baseDir . '/inc/template-classes/class-wcml-not-translatable-attributes.php',
351
  'WCML_Orders' => $baseDir . '/inc/class-wcml-orders.php',
 
352
  'WCML_Per_Product_Shipping' => $baseDir . '/compatibility/class-wcml-per-product-shipping.php',
353
  'WCML_Pip' => $baseDir . '/compatibility/class-wcml-pip.php',
354
  'WCML_Plugins_Wrap' => $baseDir . '/inc/template-classes/class-wcml-plugins-wrap.php',
@@ -360,7 +362,8 @@ return array(
360
  'WCML_Products' => $baseDir . '/inc/class-wcml-products.php',
361
  'WCML_Products_Screen_Options' => $baseDir . '/inc/class-wcml-products-screen-options.php',
362
  'WCML_Products_UI' => $baseDir . '/inc/template-classes/class-wcml-products-ui.php',
363
- 'WCML_REST_API_Support' => $baseDir . '/inc/rest-api-support/class-wcml-rest-api-suport.php',
 
364
  'WCML_Removed_Cart_Items_UI' => $baseDir . '/inc/template-classes/class-wcml-removed-cart-items-ui.php',
365
  'WCML_Reports' => $baseDir . '/inc/class-wcml-reports.php',
366
  'WCML_Requests' => $baseDir . '/inc/class-wcml-requests.php',
@@ -390,6 +393,7 @@ return array(
390
  'WCML_TP_Support' => $baseDir . '/inc/class-wcml-tp-support.php',
391
  'WCML_Tab_Manager' => $baseDir . '/compatibility/class-wcml-tab-manager.php',
392
  'WCML_Table_Rate_Shipping' => $baseDir . '/compatibility/class-wcml-table-rate-shipping.php',
 
393
  'WCML_Terms' => $baseDir . '/inc/class-wcml-terms.php',
394
  'WCML_The_Events_Calendar' => $baseDir . '/compatibility/class-wcml-the-events-calendar.php',
395
  'WCML_Translation_Editor' => $baseDir . '/inc/translation-editor/class-wcml-translation-editor.php',
@@ -400,8 +404,10 @@ return array(
400
  'WCML_Variation_Swatches_and_Photos' => $baseDir . '/compatibility/class-wcml-variation-swatches-and-photos.php',
401
  'WCML_Vpc' => $baseDir . '/compatibility/class-wcml-vpc.php',
402
  'WCML_W3TC_Multi_Currency' => $baseDir . '/inc/currencies/class-wcml-w3tc-multi-currency.php',
 
403
  'WCML_WC_Ajax_Cart' => $baseDir . '/compatibility/class-wcml-wc-ajax-cart.php',
404
  'WCML_WC_Gateways' => $baseDir . '/inc/class-wcml-wc-gateways.php',
 
405
  'WCML_WC_Name_Your_Price' => $baseDir . '/compatibility/class-wcml-wc-name-your-price.php',
406
  'WCML_WC_Product_Bundles_Items' => $baseDir . '/compatibility/includes/class-wcml-wc-product-bundles-items.php',
407
  'WCML_WC_Shipping' => $baseDir . '/inc/class-wcml-wc-shipping.php',
@@ -410,6 +416,7 @@ return array(
410
  'WCML_WPSEO' => $baseDir . '/compatibility/class-wcml-wpseo.php',
411
  'WCML_Widgets' => $baseDir . '/inc/class-wcml-widgets.php',
412
  'WCML_WooCommerce_Rest_API_Support' => $baseDir . '/inc/class-wcml-woocommerce-rest-api-support.php',
 
413
  'WCML_gravityforms' => $baseDir . '/compatibility/class-wcml-gravityforms.php',
414
  'WCML_sensei' => $baseDir . '/compatibility/class-wcml-sensei.php',
415
  'WCML_wcExporter' => $baseDir . '/compatibility/class-wcml-wcexporter.php',
328
  'WCML_Flatsome' => $baseDir . '/compatibility/class-wcml-flatsome.php',
329
  'WCML_Install' => $baseDir . '/inc/class-wcml-install.php',
330
  'WCML_JCK_WSSV' => $baseDir . '/compatibility/class-wcml-jck-wssv.php',
331
+ 'WCML_Klarna_Gateway' => $baseDir . '/compatibility/class-wcml-klarna-gateway.php',
332
  'WCML_Languages_Upgrade_Notice' => $baseDir . '/inc/template-classes/class-wcml-languages-upgrade-notice.php',
333
  'WCML_Languages_Upgrader' => $baseDir . '/inc/class-wcml-languages-upgrader.php',
334
  'WCML_Links' => $baseDir . '/inc/admin-menus/class-wcml-links.php',
350
  'WCML_Multi_Currency_UI' => $baseDir . '/inc/template-classes/multi-currency/class-wcml-multi-currency-ui.php',
351
  'WCML_Not_Translatable_Attributes' => $baseDir . '/inc/template-classes/class-wcml-not-translatable-attributes.php',
352
  'WCML_Orders' => $baseDir . '/inc/class-wcml-orders.php',
353
+ 'WCML_Page_Builders' => $baseDir . '/inc/translation-editor/class-wcml-page-builders.php',
354
  'WCML_Per_Product_Shipping' => $baseDir . '/compatibility/class-wcml-per-product-shipping.php',
355
  'WCML_Pip' => $baseDir . '/compatibility/class-wcml-pip.php',
356
  'WCML_Plugins_Wrap' => $baseDir . '/inc/template-classes/class-wcml-plugins-wrap.php',
362
  'WCML_Products' => $baseDir . '/inc/class-wcml-products.php',
363
  'WCML_Products_Screen_Options' => $baseDir . '/inc/class-wcml-products-screen-options.php',
364
  'WCML_Products_UI' => $baseDir . '/inc/template-classes/class-wcml-products-ui.php',
365
+ 'WCML_REST_API_Support' => $baseDir . '/inc/rest-api-support/class-wcml-rest-api-support.php',
366
+ 'WCML_REST_API_Support_V1' => $baseDir . '/inc/rest-api-support/class-wcml-rest-api-support-v1.php',
367
  'WCML_Removed_Cart_Items_UI' => $baseDir . '/inc/template-classes/class-wcml-removed-cart-items-ui.php',
368
  'WCML_Reports' => $baseDir . '/inc/class-wcml-reports.php',
369
  'WCML_Requests' => $baseDir . '/inc/class-wcml-requests.php',
393
  'WCML_TP_Support' => $baseDir . '/inc/class-wcml-tp-support.php',
394
  'WCML_Tab_Manager' => $baseDir . '/compatibility/class-wcml-tab-manager.php',
395
  'WCML_Table_Rate_Shipping' => $baseDir . '/compatibility/class-wcml-table-rate-shipping.php',
396
+ 'WCML_Taxonomy_Translation_Link_Filters' => $baseDir . '/inc/admin-menus/class-wcml-taxonomy-translation-link-filters.php',
397
  'WCML_Terms' => $baseDir . '/inc/class-wcml-terms.php',
398
  'WCML_The_Events_Calendar' => $baseDir . '/compatibility/class-wcml-the-events-calendar.php',
399
  'WCML_Translation_Editor' => $baseDir . '/inc/translation-editor/class-wcml-translation-editor.php',
404
  'WCML_Variation_Swatches_and_Photos' => $baseDir . '/compatibility/class-wcml-variation-swatches-and-photos.php',
405
  'WCML_Vpc' => $baseDir . '/compatibility/class-wcml-vpc.php',
406
  'WCML_W3TC_Multi_Currency' => $baseDir . '/inc/currencies/class-wcml-w3tc-multi-currency.php',
407
+ 'WCML_WC_Admin_Duplicate_Product' => $baseDir . '/inc/translation-editor/class-wcml-wc-admin-duplicate-product.php',
408
  'WCML_WC_Ajax_Cart' => $baseDir . '/compatibility/class-wcml-wc-ajax-cart.php',
409
  'WCML_WC_Gateways' => $baseDir . '/inc/class-wcml-wc-gateways.php',
410
+ 'WCML_WC_Memberships' => $baseDir . '/compatibility/class-wcml-wc-memberships.php',
411
  'WCML_WC_Name_Your_Price' => $baseDir . '/compatibility/class-wcml-wc-name-your-price.php',
412
  'WCML_WC_Product_Bundles_Items' => $baseDir . '/compatibility/includes/class-wcml-wc-product-bundles-items.php',
413
  'WCML_WC_Shipping' => $baseDir . '/inc/class-wcml-wc-shipping.php',
416
  'WCML_WPSEO' => $baseDir . '/compatibility/class-wcml-wpseo.php',
417
  'WCML_Widgets' => $baseDir . '/inc/class-wcml-widgets.php',
418
  'WCML_WooCommerce_Rest_API_Support' => $baseDir . '/inc/class-wcml-woocommerce-rest-api-support.php',
419
+ 'WCML_YITH_WCQV' => $baseDir . '/compatibility/class-wcml-yith-wcqv.php',
420
  'WCML_gravityforms' => $baseDir . '/compatibility/class-wcml-gravityforms.php',
421
  'WCML_sensei' => $baseDir . '/compatibility/class-wcml-sensei.php',
422
  'WCML_wcExporter' => $baseDir . '/compatibility/class-wcml-wcexporter.php',
vendor/composer/autoload_real.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
- class ComposerAutoloaderInitb607dde9b5d8295faf917ebd1312c1e1
6
  {
7
  private static $loader;
8
 
@@ -19,15 +19,15 @@ class ComposerAutoloaderInitb607dde9b5d8295faf917ebd1312c1e1
19
  return self::$loader;
20
  }
21
 
22
- spl_autoload_register(array('ComposerAutoloaderInitb607dde9b5d8295faf917ebd1312c1e1', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
- spl_autoload_unregister(array('ComposerAutoloaderInitb607dde9b5d8295faf917ebd1312c1e1', 'loadClassLoader'));
25
 
26
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
27
  if ($useStaticLoader) {
28
  require_once __DIR__ . '/autoload_static.php';
29
 
30
- call_user_func(\Composer\Autoload\ComposerStaticInitb607dde9b5d8295faf917ebd1312c1e1::getInitializer($loader));
31
  } else {
32
  $map = require __DIR__ . '/autoload_namespaces.php';
33
  foreach ($map as $namespace => $path) {
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
+ class ComposerAutoloaderInitb9ffed287a5b4e2fcc802a91254f114a
6
  {
7
  private static $loader;
8
 
19
  return self::$loader;
20
  }
21
 
22
+ spl_autoload_register(array('ComposerAutoloaderInitb9ffed287a5b4e2fcc802a91254f114a', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInitb9ffed287a5b4e2fcc802a91254f114a', 'loadClassLoader'));
25
 
26
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
27
  if ($useStaticLoader) {
28
  require_once __DIR__ . '/autoload_static.php';
29
 
30
+ call_user_func(\Composer\Autoload\ComposerStaticInitb9ffed287a5b4e2fcc802a91254f114a::getInitializer($loader));
31
  } else {
32
  $map = require __DIR__ . '/autoload_namespaces.php';
33
  foreach ($map as $namespace => $path) {
vendor/composer/autoload_real_52.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real_52.php generated by xrstf/composer-php52
4
 
5
- class ComposerAutoloaderInit88b7ad9735ac37cb213cb9c6587b3e8d {
6
  private static $loader;
7
 
8
  public static function loadClassLoader($class) {
@@ -19,9 +19,9 @@ class ComposerAutoloaderInit88b7ad9735ac37cb213cb9c6587b3e8d {
19
  return self::$loader;
20
  }
21
 
22
- spl_autoload_register(array('ComposerAutoloaderInit88b7ad9735ac37cb213cb9c6587b3e8d', 'loadClassLoader'), true /*, true */);
23
  self::$loader = $loader = new xrstf_Composer52_ClassLoader();
24
- spl_autoload_unregister(array('ComposerAutoloaderInit88b7ad9735ac37cb213cb9c6587b3e8d', 'loadClassLoader'));
25
 
26
  $vendorDir = dirname(dirname(__FILE__));
27
  $baseDir = dirname($vendorDir);
2
 
3
  // autoload_real_52.php generated by xrstf/composer-php52
4
 
5
+ class ComposerAutoloaderInit38be79df74f6b23b0833390c6a01eb02 {
6
  private static $loader;
7
 
8
  public static function loadClassLoader($class) {
19
  return self::$loader;
20
  }
21
 
22
+ spl_autoload_register(array('ComposerAutoloaderInit38be79df74f6b23b0833390c6a01eb02', 'loadClassLoader'), true /*, true */);
23
  self::$loader = $loader = new xrstf_Composer52_ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInit38be79df74f6b23b0833390c6a01eb02', 'loadClassLoader'));
25
 
26
  $vendorDir = dirname(dirname(__FILE__));
27
  $baseDir = dirname($vendorDir);
vendor/composer/autoload_static.php CHANGED
@@ -4,7 +4,7 @@
4
 
5
  namespace Composer\Autoload;
6
 
7
- class ComposerStaticInitb607dde9b5d8295faf917ebd1312c1e1
8
  {
9
  public static $prefixLengthsPsr4 = array (
10
  'C' =>
@@ -360,6 +360,7 @@ class ComposerStaticInitb607dde9b5d8295faf917ebd1312c1e1
360
  'WCML_Flatsome' => __DIR__ . '/../..' . '/compatibility/class-wcml-flatsome.php',
361
  'WCML_Install' => __DIR__ . '/../..' . '/inc/class-wcml-install.php',
362
  'WCML_JCK_WSSV' => __DIR__ . '/../..' . '/compatibility/class-wcml-jck-wssv.php',
 
363
  'WCML_Languages_Upgrade_Notice' => __DIR__ . '/../..' . '/inc/template-classes/class-wcml-languages-upgrade-notice.php',
364
  'WCML_Languages_Upgrader' => __DIR__ . '/../..' . '/inc/class-wcml-languages-upgrader.php',
365
  'WCML_Links' => __DIR__ . '/../..' . '/inc/admin-menus/class-wcml-links.php',
@@ -381,6 +382,7 @@ class ComposerStaticInitb607dde9b5d8295faf917ebd1312c1e1
381
  'WCML_Multi_Currency_UI' => __DIR__ . '/../..' . '/inc/template-classes/multi-currency/class-wcml-multi-currency-ui.php',
382
  'WCML_Not_Translatable_Attributes' => __DIR__ . '/../..' . '/inc/template-classes/class-wcml-not-translatable-attributes.php',
383
  'WCML_Orders' => __DIR__ . '/../..' . '/inc/class-wcml-orders.php',
 
384
  'WCML_Per_Product_Shipping' => __DIR__ . '/../..' . '/compatibility/class-wcml-per-product-shipping.php',
385
  'WCML_Pip' => __DIR__ . '/../..' . '/compatibility/class-wcml-pip.php',
386
  'WCML_Plugins_Wrap' => __DIR__ . '/../..' . '/inc/template-classes/class-wcml-plugins-wrap.php',
@@ -392,7 +394,8 @@ class ComposerStaticInitb607dde9b5d8295faf917ebd1312c1e1
392
  'WCML_Products' => __DIR__ . '/../..' . '/inc/class-wcml-products.php',
393
  'WCML_Products_Screen_Options' => __DIR__ . '/../..' . '/inc/class-wcml-products-screen-options.php',
394
  'WCML_Products_UI' => __DIR__ . '/../..' . '/inc/template-classes/class-wcml-products-ui.php',
395
- 'WCML_REST_API_Support' => __DIR__ . '/../..' . '/inc/rest-api-support/class-wcml-rest-api-suport.php',
 
396
  'WCML_Removed_Cart_Items_UI' => __DIR__ . '/../..' . '/inc/template-classes/class-wcml-removed-cart-items-ui.php',
397
  'WCML_Reports' => __DIR__ . '/../..' . '/inc/class-wcml-reports.php',
398
  'WCML_Requests' => __DIR__ . '/../..' . '/inc/class-wcml-requests.php',
@@ -422,6 +425,7 @@ class ComposerStaticInitb607dde9b5d8295faf917ebd1312c1e1
422
  'WCML_TP_Support' => __DIR__ . '/../..' . '/inc/class-wcml-tp-support.php',
423
  'WCML_Tab_Manager' => __DIR__ . '/../..' . '/compatibility/class-wcml-tab-manager.php',
424
  'WCML_Table_Rate_Shipping' => __DIR__ . '/../..' . '/compatibility/class-wcml-table-rate-shipping.php',
 
425
  'WCML_Terms' => __DIR__ . '/../..' . '/inc/class-wcml-terms.php',
426
  'WCML_The_Events_Calendar' => __DIR__ . '/../..' . '/compatibility/class-wcml-the-events-calendar.php',
427
  'WCML_Translation_Editor' => __DIR__ . '/../..' . '/inc/translation-editor/class-wcml-translation-editor.php',
@@ -432,8 +436,10 @@ class ComposerStaticInitb607dde9b5d8295faf917ebd1312c1e1
432
  'WCML_Variation_Swatches_and_Photos' => __DIR__ . '/../..' . '/compatibility/class-wcml-variation-swatches-and-photos.php',
433
  'WCML_Vpc' => __DIR__ . '/../..' . '/compatibility/class-wcml-vpc.php',
434
  'WCML_W3TC_Multi_Currency' => __DIR__ . '/../..' . '/inc/currencies/class-wcml-w3tc-multi-currency.php',
 
435
  'WCML_WC_Ajax_Cart' => __DIR__ . '/../..' . '/compatibility/class-wcml-wc-ajax-cart.php',
436
  'WCML_WC_Gateways' => __DIR__ . '/../..' . '/inc/class-wcml-wc-gateways.php',
 
437
  'WCML_WC_Name_Your_Price' => __DIR__ . '/../..' . '/compatibility/class-wcml-wc-name-your-price.php',
438
  'WCML_WC_Product_Bundles_Items' => __DIR__ . '/../..' . '/compatibility/includes/class-wcml-wc-product-bundles-items.php',
439
  'WCML_WC_Shipping' => __DIR__ . '/../..' . '/inc/class-wcml-wc-shipping.php',
@@ -442,6 +448,7 @@ class ComposerStaticInitb607dde9b5d8295faf917ebd1312c1e1
442
  'WCML_WPSEO' => __DIR__ . '/../..' . '/compatibility/class-wcml-wpseo.php',
443
  'WCML_Widgets' => __DIR__ . '/../..' . '/inc/class-wcml-widgets.php',
444
  'WCML_WooCommerce_Rest_API_Support' => __DIR__ . '/../..' . '/inc/class-wcml-woocommerce-rest-api-support.php',
 
445
  'WCML_gravityforms' => __DIR__ . '/../..' . '/compatibility/class-wcml-gravityforms.php',
446
  'WCML_sensei' => __DIR__ . '/../..' . '/compatibility/class-wcml-sensei.php',
447
  'WCML_wcExporter' => __DIR__ . '/../..' . '/compatibility/class-wcml-wcexporter.php',
@@ -455,10 +462,10 @@ class ComposerStaticInitb607dde9b5d8295faf917ebd1312c1e1
455
  public static function getInitializer(ClassLoader $loader)
456
  {
457
  return \Closure::bind(function () use ($loader) {
458
- $loader->prefixLengthsPsr4 = ComposerStaticInitb607dde9b5d8295faf917ebd1312c1e1::$prefixLengthsPsr4;
459
- $loader->prefixDirsPsr4 = ComposerStaticInitb607dde9b5d8295faf917ebd1312c1e1::$prefixDirsPsr4;
460
- $loader->prefixesPsr0 = ComposerStaticInitb607dde9b5d8295faf917ebd1312c1e1::$prefixesPsr0;
461
- $loader->classMap = ComposerStaticInitb607dde9b5d8295faf917ebd1312c1e1::$classMap;
462
 
463
  }, null, ClassLoader::class);
464
  }
4
 
5
  namespace Composer\Autoload;
6
 
7
+ class ComposerStaticInitb9ffed287a5b4e2fcc802a91254f114a
8
  {
9
  public static $prefixLengthsPsr4 = array (
10
  'C' =>
360
  'WCML_Flatsome' => __DIR__ . '/../..' . '/compatibility/class-wcml-flatsome.php',
361
  'WCML_Install' => __DIR__ . '/../..' . '/inc/class-wcml-install.php',
362
  'WCML_JCK_WSSV' => __DIR__ . '/../..' . '/compatibility/class-wcml-jck-wssv.php',
363
+ 'WCML_Klarna_Gateway' => __DIR__ . '/../..' . '/compatibility/class-wcml-klarna-gateway.php',
364
  'WCML_Languages_Upgrade_Notice' => __DIR__ . '/../..' . '/inc/template-classes/class-wcml-languages-upgrade-notice.php',
365
  'WCML_Languages_Upgrader' => __DIR__ . '/../..' . '/inc/class-wcml-languages-upgrader.php',
366
  'WCML_Links' => __DIR__ . '/../..' . '/inc/admin-menus/class-wcml-links.php',
382
  'WCML_Multi_Currency_UI' => __DIR__ . '/../..' . '/inc/template-classes/multi-currency/class-wcml-multi-currency-ui.php',
383
  'WCML_Not_Translatable_Attributes' => __DIR__ . '/../..' . '/inc/template-classes/class-wcml-not-translatable-attributes.php',
384
  'WCML_Orders' => __DIR__ . '/../..' . '/inc/class-wcml-orders.php',
385
+ 'WCML_Page_Builders' => __DIR__ . '/../..' . '/inc/translation-editor/class-wcml-page-builders.php',
386
  'WCML_Per_Product_Shipping' => __DIR__ . '/../..' . '/compatibility/class-wcml-per-product-shipping.php',
387
  'WCML_Pip' => __DIR__ . '/../..' . '/compatibility/class-wcml-pip.php',
388
  'WCML_Plugins_Wrap' => __DIR__ . '/../..' . '/inc/template-classes/class-wcml-plugins-wrap.php',
394
  'WCML_Products' => __DIR__ . '/../..' . '/inc/class-wcml-products.php',
395
  'WCML_Products_Screen_Options' => __DIR__ . '/../..' . '/inc/class-wcml-products-screen-options.php',
396
  'WCML_Products_UI' => __DIR__ . '/../..' . '/inc/template-classes/class-wcml-products-ui.php',
397
+ 'WCML_REST_API_Support' => __DIR__ . '/../..' . '/inc/rest-api-support/class-wcml-rest-api-support.php',
398
+ 'WCML_REST_API_Support_V1' => __DIR__ . '/../..' . '/inc/rest-api-support/class-wcml-rest-api-support-v1.php',
399
  'WCML_Removed_Cart_Items_UI' => __DIR__ . '/../..' . '/inc/template-classes/class-wcml-removed-cart-items-ui.php',
400
  'WCML_Reports' => __DIR__ . '/../..' . '/inc/class-wcml-reports.php',
401
  'WCML_Requests' => __DIR__ . '/../..' . '/inc/class-wcml-requests.php',
425
  'WCML_TP_Support' => __DIR__ . '/../..' . '/inc/class-wcml-tp-support.php',
426
  'WCML_Tab_Manager' => __DIR__ . '/../..' . '/compatibility/class-wcml-tab-manager.php',
427
  'WCML_Table_Rate_Shipping' => __DIR__ . '/../..' . '/compatibility/class-wcml-table-rate-shipping.php',
428
+ 'WCML_Taxonomy_Translation_Link_Filters' => __DIR__ . '/../..' . '/inc/admin-menus/class-wcml-taxonomy-translation-link-filters.php',
429
  'WCML_Terms' => __DIR__ . '/../..' . '/inc/class-wcml-terms.php',
430
  'WCML_The_Events_Calendar' => __DIR__ . '/../..' . '/compatibility/class-wcml-the-events-calendar.php',
431
  'WCML_Translation_Editor' => __DIR__ . '/../..' . '/inc/translation-editor/class-wcml-translation-editor.php',
436
  'WCML_Variation_Swatches_and_Photos' => __DIR__ . '/../..' . '/compatibility/class-wcml-variation-swatches-and-photos.php',
437
  'WCML_Vpc' => __DIR__ . '/../..' . '/compatibility/class-wcml-vpc.php',
438
  'WCML_W3TC_Multi_Currency' => __DIR__ . '/../..' . '/inc/currencies/class-wcml-w3tc-multi-currency.php',
439
+ 'WCML_WC_Admin_Duplicate_Product' => __DIR__ . '/../..' . '/inc/translation-editor/class-wcml-wc-admin-duplicate-product.php',
440
  'WCML_WC_Ajax_Cart' => __DIR__ . '/../..' . '/compatibility/class-wcml-wc-ajax-cart.php',
441
  'WCML_WC_Gateways' => __DIR__ . '/../..' . '/inc/class-wcml-wc-gateways.php',
442
+ 'WCML_WC_Memberships' => __DIR__ . '/../..' . '/compatibility/class-wcml-wc-memberships.php',
443
  'WCML_WC_Name_Your_Price' => __DIR__ . '/../..' . '/compatibility/class-wcml-wc-name-your-price.php',
444
  'WCML_WC_Product_Bundles_Items' => __DIR__ . '/../..' . '/compatibility/includes/class-wcml-wc-product-bundles-items.php',
445
  'WCML_WC_Shipping' => __DIR__ . '/../..' . '/inc/class-wcml-wc-shipping.php',
448
  'WCML_WPSEO' => __DIR__ . '/../..' . '/compatibility/class-wcml-wpseo.php',
449
  'WCML_Widgets' => __DIR__ . '/../..' . '/inc/class-wcml-widgets.php',
450
  'WCML_WooCommerce_Rest_API_Support' => __DIR__ . '/../..' . '/inc/class-wcml-woocommerce-rest-api-support.php',
451
+ 'WCML_YITH_WCQV' => __DIR__ . '/../..' . '/compatibility/class-wcml-yith-wcqv.php',
452
  'WCML_gravityforms' => __DIR__ . '/../..' . '/compatibility/class-wcml-gravityforms.php',
453
  'WCML_sensei' => __DIR__ . '/../..' . '/compatibility/class-wcml-sensei.php',
454
  'WCML_wcExporter' => __DIR__ . '/../..' . '/compatibility/class-wcml-wcexporter.php',
462
  public static function getInitializer(ClassLoader $loader)
463
  {
464
  return \Closure::bind(function () use ($loader) {
465
+ $loader->prefixLengthsPsr4 = ComposerStaticInitb9ffed287a5b4e2fcc802a91254f114a::$prefixLengthsPsr4;
466
+ $loader->prefixDirsPsr4 = ComposerStaticInitb9ffed287a5b4e2fcc802a91254f114a::$prefixDirsPsr4;
467
+ $loader->prefixesPsr0 = ComposerStaticInitb9ffed287a5b4e2fcc802a91254f114a::$prefixesPsr0;
468
+ $loader->classMap = ComposerStaticInitb9ffed287a5b4e2fcc802a91254f114a::$classMap;
469
 
470
  }, null, ClassLoader::class);
471
  }
wpml-woocommerce.php CHANGED
@@ -6,12 +6,12 @@
6
  Author: OnTheGoSystems
7
  Author URI: http://www.onthegosystems.com/
8
  Text Domain: woocommerce-multilingual
9
- Version: 4.1.2
10
  */
11
 
12
  if( defined( 'WCML_VERSION' ) ) return;
13
 
14
- define( 'WCML_VERSION', '4.1.2' );
15
  define( 'WCML_PLUGIN_PATH', dirname( __FILE__ ) );
16
  define( 'WCML_PLUGIN_FOLDER', basename( WCML_PLUGIN_PATH ) );
17
  define( 'WCML_LOCALE_PATH', WCML_PLUGIN_PATH . '/locale' );
@@ -43,12 +43,14 @@ if ( version_compare( PHP_VERSION, '5.3.0' ) >= 0 ) {
43
  // Load WooCommerce Multilingual when WPML is active
44
  add_action( 'wpml_loaded', array( 'woocommerce_wpml', 'instance' ) );
45
 
46
- add_action( 'wpml_before_init', array( 'WCML_REST_API_Support', 'remove_wpml_global_url_filters' ), 0 );
 
 
47
 
48
 
49
  // Load WooCommerce Multilingual when WPML is NOT active
50
- add_action('plugins_loaded', 'wpml_wcml_startup', 10000);
51
- function wpml_wcml_startup(){
52
  if( !did_action( 'wpml_loaded' ) ){
53
  global $woocommerce_wpml;
54
  $woocommerce_wpml = new woocommerce_wpml();
6
  Author: OnTheGoSystems
7
  Author URI: http://www.onthegosystems.com/
8
  Text Domain: woocommerce-multilingual
9
+ Version: 4.1.3
10
  */
11
 
12
  if( defined( 'WCML_VERSION' ) ) return;
13
 
14
+ define( 'WCML_VERSION', '4.1.3' );
15
  define( 'WCML_PLUGIN_PATH', dirname( __FILE__ ) );
16
  define( 'WCML_PLUGIN_FOLDER', basename( WCML_PLUGIN_PATH ) );
17
  define( 'WCML_LOCALE_PATH', WCML_PLUGIN_PATH . '/locale' );
43
  // Load WooCommerce Multilingual when WPML is active
44
  add_action( 'wpml_loaded', array( 'woocommerce_wpml', 'instance' ) );
45
 
46
+ if( WCML_REST_API_Support::is_rest_api_request() ){
47
+ add_action( 'wpml_before_init', array( 'WCML_REST_API_Support', 'remove_wpml_global_url_filters' ), 0 );
48
+ }
49
 
50
 
51
  // Load WooCommerce Multilingual when WPML is NOT active
52
+ add_action('plugins_loaded', 'load_wcml_without_wpml', 10000);
53
+ function load_wcml_without_wpml(){
54
  if( !did_action( 'wpml_loaded' ) ){
55
  global $woocommerce_wpml;
56
  $woocommerce_wpml = new woocommerce_wpml();