WooCommerce Multilingual – run WooCommerce with WPML - Version 4.5.0

Version Description

  • Add "get_post_metadata" hook to filter Woocommerce product data
  • Added function in troubleshooting page to fix broken variations
  • Fix refreshing of status icon when ATE Job of updated content is synced
  • Fix few notices when removing a Elementor widget and refresh page
  • Fetch ATE translations from WCML Product Translation Tab
  • Fix warning when adding comment to product
  • Fixed wrong price calculation when adding product to new order on backend
  • Fixed bookings counter on admin bookings listing page
  • Fixed stock quantity not synchronized to translation when creating it
  • Fixed notice when saving translation
  • Fixed translated attributes via ATE/Translation service not connected to translated product
  • Fix not translated "On Hold" email subject after returning order from "Processing"
  • Remove unneded $_SESSION variables on checkout page
  • Fix PHP notice Notice: Only variables should be passed by reference
  • Implemented dependency check for minimum compatible versions of required WPML plugins
  • Fixed default variation not pre-selected on front-end for translated product with non latin attribute in default language
  • Fix cannot change currency with "wcml_client_currency" filter
  • Fixed not valid API key when trying manually update exchange rates
  • WooCommerce Variation Swatches and Photos compatibility to translate attributes
  • Fix related product displays in all languages
  • Added compatibility with Yikes Custom Product Tabs
Download this release

Release Info

Developer sergey.r
Plugin Icon 128x128 WooCommerce Multilingual – run WooCommerce with WPML
Version 4.5.0
Comparing to
See all releases

Code changes from version 4.4.2.1 to 4.5.0

Files changed (55) hide show
  1. changelog/4.1.0.md +2 -0
  2. changelog/4.4.0.md +1 -1
  3. changelog/4.5.0.md +24 -0
  4. classes/ate/class-wcml-ate-activate-synchronization.php +16 -0
  5. classes/class-woocommerce-wpml.php +21 -15
  6. classes/currencies/class-wcml-admin-currency-selector.php +6 -2
  7. classes/currencies/class-wcml-currencies.php +13 -7
  8. classes/multi-currency/exchange-rate-services/class-wcml-exchange-rate-service.php +1 -11
  9. compatibility/class-wcml-bookings.php +51 -0
  10. compatibility/class-wcml-product-bundles.php +3 -3
  11. compatibility/class-wcml-variation-swatches-and-photos.php +74 -54
  12. compatibility/class-wcml-yikes-custom-product-tabs-pro.php +265 -0
  13. inc/admin-menus/class-wcml-admin-menus.php +7 -2
  14. inc/class-wcml-attributes.php +4 -3
  15. inc/class-wcml-comments.php +3 -1
  16. inc/class-wcml-compatibility.php +8 -1
  17. inc/class-wcml-emails.php +66 -49
  18. inc/class-wcml-media.php +5 -4
  19. inc/class-wcml-orders.php +5 -26
  20. inc/class-wcml-products.php +67 -5
  21. inc/class-wcml-tp-support.php +5 -2
  22. inc/class-wcml-troubleshooting.php +107 -6
  23. inc/class-wcml-upgrade.php +29 -1
  24. inc/currencies/class-wcml-custom-prices.php +1 -5
  25. inc/currencies/class-wcml-multi-currency-install.php +79 -57
  26. inc/currencies/class-wcml-multi-currency-orders.php +39 -22
  27. inc/currencies/class-wcml-multi-currency-prices.php +3 -13
  28. inc/currencies/class-wcml-multi-currency.php +3 -1
  29. inc/missing-php-functions.php +6 -0
  30. inc/template-classes/class-wcml-troubleshooting-ui.php +3 -0
  31. inc/template-classes/multi-currency/class-wcml-exchange-rates-ui.php +0 -1
  32. inc/translation-editor/class-wcml-editor-ui-product-job.php +2 -0
  33. inc/translation-editor/class-wcml-page-builders.php +21 -15
  34. inc/translation-editor/class-wcml-synchronize-product-data.php +21 -12
  35. inc/translation-editor/class-wcml-synchronize-variations-data.php +2 -0
  36. inc/translation-editor/class-wcml-translation-editor.php +13 -17
  37. inc/wcml-core-functions.php +65 -14
  38. readme.txt +29 -3
  39. res/css/management.css +1 -1
  40. res/js/lock_fields.js +2 -0
  41. res/js/lock_fields.min.js +1 -1
  42. res/js/troubleshooting.js +32 -0
  43. res/js/troubleshooting.min.js +1 -1
  44. templates/multi-currency/exchange-rates.twig +0 -3
  45. templates/troubleshooting.twig +10 -0
  46. vendor/autoload.php +1 -1
  47. vendor/autoload_52.php +1 -1
  48. vendor/composer/autoload_classmap.php +5 -1
  49. vendor/composer/autoload_real.php +7 -7
  50. vendor/composer/autoload_real_52.php +3 -3
  51. vendor/composer/autoload_static.php +10 -6
  52. vendor/wpml-shared/wpml-lib-dependencies/src/dependencies/class-wpml-core-version-check.php +24 -0
  53. vendor/wpml-shared/wpml-lib-dependencies/src/dependencies/class-wpml-dependencies.php +348 -0
  54. wpml-dependencies.json +6 -0
  55. wpml-woocommerce.php +13 -10
changelog/4.1.0.md ADDED
@@ -0,0 +1,2 @@
 
 
1
+ # Fixes
2
+ * [wcml-1712] Fixed bookings issues
changelog/4.4.0.md CHANGED
@@ -3,7 +3,6 @@
3
  * [wcml-2641] Fix and removed duplicated entries in code
4
  * [wcml-2625] Hide reviews in other languages link, if there are no reviews in product
5
  * [wcml-2594] Update WCML Logo
6
- * [wcml-2539] Added support for wpml endpoints
7
  * [wcml-2375] Removed Product Type Column from WCML backend and added compatibility with the WC Product Type Column plugin
8
 
9
  # Fixes
@@ -39,6 +38,7 @@
39
  * [wcml-2568] Fixed missed synchronization of 'outofstock' visibility term between product translations
40
  * [wcml-2566] Fix broken logic with Table Rate Shipping when product uses class with "break and abort" rule
41
  * [wcml-2550] Custom attributes terms not copied to diplicated translation after update values in original
 
42
  * [wcml-2538] WP Fastest Cache compatibility - fixed currency switcher problem
43
  * [wcml-2532] Added ability to set custom prices for secondary currencies in WC Product Add-Ons
44
  * [wcml-2201] Update minimum requirements
3
  * [wcml-2641] Fix and removed duplicated entries in code
4
  * [wcml-2625] Hide reviews in other languages link, if there are no reviews in product
5
  * [wcml-2594] Update WCML Logo
 
6
  * [wcml-2375] Removed Product Type Column from WCML backend and added compatibility with the WC Product Type Column plugin
7
 
8
  # Fixes
38
  * [wcml-2568] Fixed missed synchronization of 'outofstock' visibility term between product translations
39
  * [wcml-2566] Fix broken logic with Table Rate Shipping when product uses class with "break and abort" rule
40
  * [wcml-2550] Custom attributes terms not copied to diplicated translation after update values in original
41
+ * [wcml-2539] Added support for wpml endpoints
42
  * [wcml-2538] WP Fastest Cache compatibility - fixed currency switcher problem
43
  * [wcml-2532] Added ability to set custom prices for secondary currencies in WC Product Add-Ons
44
  * [wcml-2201] Update minimum requirements
changelog/4.5.0.md ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Features
2
+ * [wcml-2657] Add "get_post_metadata" hook to filter Woocommerce product data
3
+ * [wcml-2138] Added function in troubleshooting page to fix broken variations
4
+
5
+ # Fixes
6
+ * [wcml-2734] Fix refreshing of status icon when ATE Job of updated content is synced
7
+ * [wcml-2727] Fix few notices when removing a Elementor widget and refresh page
8
+ * [wcml-2722] Fetch ATE translations from WCML Product Translation Tab
9
+ * [wcml-2704] Fix warning when adding comment to product
10
+ * [wcml-2703] Fixed wrong price calculation when adding product to new order on backend
11
+ * [wcml-2701] Fixed bookings counter on admin bookings listing page
12
+ * [wcml-2694] Fixed stock quantity not synchronized to translation when creating it
13
+ * [wcml-2690] Fixed notice when saving translation
14
+ * [wcml-2689] Fixed translated attributes via ATE/Translation service not connected to translated product
15
+ * [wcml-2687] Fix not translated "On Hold" email subject after returning order from "Processing"
16
+ * [wcml-2683] Remove unneded $_SESSION variables on checkout page
17
+ * [wcml-2682] Fix PHP notice `Notice: Only variables should be passed by reference`
18
+ * [wcml-2680] Implemented dependency check for minimum compatible versions of required WPML plugins
19
+ * [wcml-2679] Fixed default variation not pre-selected on front-end for translated product with non latin attribute in default language
20
+ * [wcml-2678] Fix cannot change currency with "wcml_client_currency" filter
21
+ * [wcml-2675] Fixed not valid API key when trying manually update exchange rates
22
+ * [wcml-2674] WooCommerce Variation Swatches and Photos compatibility to translate attributes
23
+ * [wcml-2655] Fix related product displays in all languages
24
+ * [wcml-2495] Added compatibility with Yikes Custom Product Tabs
classes/ate/class-wcml-ate-activate-synchronization.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WCML_ATE_Activate_Synchronization implements IWPML_Action, IWPML_Backend_Action_Loader {
4
+ public function add_hooks() {
5
+ if ( isset( $_GET['page'] ) && 'wpml-wcml' === $_GET['page'] ) {
6
+ add_filter( 'wpml_tm_load_ate_jobs_synchronization', '__return_true' );
7
+ }
8
+ }
9
+
10
+ /**
11
+ * @return WCML_ATE_Activate_Synchronization
12
+ */
13
+ public function create() {
14
+ return $this;
15
+ }
16
+ }
classes/class-woocommerce-wpml.php CHANGED
@@ -44,10 +44,12 @@ class woocommerce_wpml {
44
  public $shipping;
45
  /** @var WCML_WC_Gateways */
46
  public $gateways;
47
- /** @var WCML_CS_Templates */
48
  public $cs_templates;
49
  /** @var WCML_Comments */
50
  public $comments;
 
 
51
 
52
  /** @var WCML_Reports */
53
  private $reports;
@@ -60,7 +62,7 @@ class woocommerce_wpml {
60
  private $xdomain_data;
61
 
62
  /**
63
- * @var WCML_Screen_Options
64
  */
65
  private $wcml_products_screen;
66
 
@@ -171,13 +173,20 @@ class woocommerce_wpml {
171
  }
172
 
173
  $this->currencies = new WCML_Currencies( $this );
174
- $this->currencies->add_hooks();if( is_admin() ) {
175
- $this->troubleshooting = new WCML_Troubleshooting( $this, $sitepress, $wpdb );
176
- $this->translation_editor = new WCML_Translation_Editor($this, $sitepress, $wpdb);
 
177
  $this->translation_editor->add_hooks();
 
 
 
 
 
 
 
 
178
  $this->languages_upgrader = new WCML_Languages_Upgrader;
179
- $this->sync_variations_data = new WCML_Synchronize_Variations_Data($this, $sitepress, $wpdb);
180
- $this->sync_variations_data->add_hooks();
181
  $this->wcml_products_screen = new WCML_Products_Screen_Options($sitepress);
182
  $this->wcml_products_screen->init();
183
  $wcml_pointers = new WCML_Pointers();
@@ -226,6 +235,11 @@ class woocommerce_wpml {
226
  $this->comments = new WCML_Comments( $this, $sitepress, $wpml_post_translations );
227
  $this->comments->add_hooks();
228
 
 
 
 
 
 
229
  $payment_method_filter = new WCML_Payment_Method_Filter();
230
  $payment_method_filter->add_hooks();
231
 
@@ -239,14 +253,6 @@ class woocommerce_wpml {
239
  $url_filters_redirect_location->add_hooks();
240
 
241
  add_action( 'wp_ajax_wcml_update_setting_ajx', array( $this, 'update_setting_ajx' ) );
242
-
243
- if ( is_admin() ) {
244
- $taxonomy_translation_link_filters = new WCML_Taxonomy_Translation_Link_Filters( $this->attributes );
245
- $taxonomy_translation_link_filters->add_filters();
246
-
247
- $tp_support = new WCML_TP_Support( $this, $wpdb , new WPML_Element_Translation_Package );
248
- $tp_support->add_hooks();
249
- }
250
  }
251
 
252
  public function get_settings(){
44
  public $shipping;
45
  /** @var WCML_WC_Gateways */
46
  public $gateways;
47
+ /** @var WCML_Currency_Switcher_Templates */
48
  public $cs_templates;
49
  /** @var WCML_Comments */
50
  public $comments;
51
+ /** @var WCML_Translation_Editor */
52
+ public $translation_editor;
53
 
54
  /** @var WCML_Reports */
55
  private $reports;
62
  private $xdomain_data;
63
 
64
  /**
65
+ * @var WCML_Products_Screen_Options
66
  */
67
  private $wcml_products_screen;
68
 
173
  }
174
 
175
  $this->currencies = new WCML_Currencies( $this );
176
+ $this->currencies->add_hooks();
177
+
178
+ if( is_admin() || wpml_is_rest_request() ) {
179
+ $this->translation_editor = new WCML_Translation_Editor($this, $sitepress, $wpdb);
180
  $this->translation_editor->add_hooks();
181
+ $tp_support = new WCML_TP_Support( $this, $wpdb , new WPML_Element_Translation_Package );
182
+ $tp_support->add_hooks();
183
+ $this->sync_variations_data = new WCML_Synchronize_Variations_Data($this, $sitepress, $wpdb);
184
+ }
185
+
186
+ if( is_admin() ) {
187
+ $this->sync_variations_data->add_hooks();
188
+ $this->troubleshooting = new WCML_Troubleshooting( $this, $sitepress, $wpdb );
189
  $this->languages_upgrader = new WCML_Languages_Upgrader;
 
 
190
  $this->wcml_products_screen = new WCML_Products_Screen_Options($sitepress);
191
  $this->wcml_products_screen->init();
192
  $wcml_pointers = new WCML_Pointers();
235
  $this->comments = new WCML_Comments( $this, $sitepress, $wpml_post_translations );
236
  $this->comments->add_hooks();
237
 
238
+ if( is_admin() ) {
239
+ $taxonomy_translation_link_filters = new WCML_Taxonomy_Translation_Link_Filters( $this->attributes );
240
+ $taxonomy_translation_link_filters->add_filters();
241
+ }
242
+
243
  $payment_method_filter = new WCML_Payment_Method_Filter();
244
  $payment_method_filter->add_hooks();
245
 
253
  $url_filters_redirect_location->add_hooks();
254
 
255
  add_action( 'wp_ajax_wcml_update_setting_ajx', array( $this, 'update_setting_ajx' ) );
 
 
 
 
 
 
 
 
256
  }
257
 
258
  public function get_settings(){
classes/currencies/class-wcml-admin-currency-selector.php CHANGED
@@ -109,7 +109,9 @@ class WCML_Admin_Currency_Selector {
109
  * @param string $currency_code
110
  */
111
  public function set_dashboard_currency( $currency_code = '' ) {
112
- if ( ! $currency_code && ! headers_sent() ) {
 
 
113
  $order_currencies = $this->woocommerce_wpml->multi_currency->orders->get_orders_currencies();
114
  $currency_code = get_woocommerce_currency();
115
  if ( ! isset( $order_currencies[ $currency_code ] ) ) {
@@ -117,7 +119,9 @@ class WCML_Admin_Currency_Selector {
117
  }
118
  }
119
 
120
- $this->currency_cookie->set_value( $currency_code, time() + DAY_IN_SECONDS );
 
 
121
  }
122
 
123
  /**
109
  * @param string $currency_code
110
  */
111
  public function set_dashboard_currency( $currency_code = '' ) {
112
+ global $pagenow;
113
+
114
+ if ( ! $currency_code && 'index.php' === $pagenow && ! headers_sent() ) {
115
  $order_currencies = $this->woocommerce_wpml->multi_currency->orders->get_orders_currencies();
116
  $currency_code = get_woocommerce_currency();
117
  if ( ! isset( $order_currencies[ $currency_code ] ) ) {
119
  }
120
  }
121
 
122
+ if ( $currency_code ) {
123
+ $this->currency_cookie->set_value( $currency_code, time() + DAY_IN_SECONDS );
124
+ }
125
  }
126
 
127
  /**
classes/currencies/class-wcml-currencies.php CHANGED
@@ -6,36 +6,42 @@
6
  class WCML_Currencies {
7
 
8
  /**
9
- * @var woocommerce_wpml
 
 
10
  */
11
  private $woocommerce_wpml;
12
- /**
13
 
14
  /**
15
  * WCML_Currencies constructor.
16
  *
17
- * @param woocommerce_wpml $woocommerce_wpml
18
  */
19
  public function __construct( woocommerce_wpml $woocommerce_wpml ) {
20
  $this->woocommerce_wpml = $woocommerce_wpml;
21
  }
22
 
 
 
 
23
  public function add_hooks() {
24
  if ( is_admin() && wcml_is_multi_currency_on() ) {
25
  add_action( 'update_option_woocommerce_currency', array(
26
  $this,
27
- 'setup_multi_currency_on_currency_update'
28
  ), 10, 2 );
29
  }
30
  }
31
 
32
  /**
33
- * @param string $old_value
34
- * @param string $new_value
 
 
35
  */
36
  public function setup_multi_currency_on_currency_update( $old_value, $new_value ) {
37
  $multi_currency_install = new WCML_Multi_Currency_Install( new WCML_Multi_Currency(), $this->woocommerce_wpml );
38
  $multi_currency_install->set_default_currencies_languages( $old_value, $new_value );
39
  }
40
 
41
- }
6
  class WCML_Currencies {
7
 
8
  /**
9
+ * The \woocommerce_wpml instance.
10
+ *
11
+ * @var \woocommerce_wpml
12
  */
13
  private $woocommerce_wpml;
 
14
 
15
  /**
16
  * WCML_Currencies constructor.
17
  *
18
+ * @param \woocommerce_wpml $woocommerce_wpml And instance of \woocommerce_wpml.
19
  */
20
  public function __construct( woocommerce_wpml $woocommerce_wpml ) {
21
  $this->woocommerce_wpml = $woocommerce_wpml;
22
  }
23
 
24
+ /**
25
+ * It hooks to `update_option_woocommerce_currency` if the conditions are right.
26
+ */
27
  public function add_hooks() {
28
  if ( is_admin() && wcml_is_multi_currency_on() ) {
29
  add_action( 'update_option_woocommerce_currency', array(
30
  $this,
31
+ 'setup_multi_currency_on_currency_update',
32
  ), 10, 2 );
33
  }
34
  }
35
 
36
  /**
37
+ * It sets the default currency for each language.
38
+ *
39
+ * @param string $old_value The value of the option before the update.
40
+ * @param string $new_value The new value of the option.
41
  */
42
  public function setup_multi_currency_on_currency_update( $old_value, $new_value ) {
43
  $multi_currency_install = new WCML_Multi_Currency_Install( new WCML_Multi_Currency(), $this->woocommerce_wpml );
44
  $multi_currency_install->set_default_currencies_languages( $old_value, $new_value );
45
  }
46
 
47
+ }
classes/multi-currency/exchange-rate-services/class-wcml-exchange-rate-service.php CHANGED
@@ -36,10 +36,7 @@ abstract class WCML_Exchange_Rate_Service {
36
 
37
  $this->settings = get_option( 'wcml_exchange_rate_service_' . $this->id, array() );
38
 
39
- if ( $this->is_key_required() ) {
40
- $this->api_key = $this->get_setting( 'api-key' );
41
- }
42
-
43
  }
44
 
45
  /**
@@ -93,13 +90,6 @@ abstract class WCML_Exchange_Rate_Service {
93
  $this->save_settings();
94
  }
95
 
96
- /**
97
- * @return bool
98
- */
99
- public function is_key_required() {
100
- return $this->requires_key;
101
- }
102
-
103
  /**
104
  * @param string $error_message
105
  */
36
 
37
  $this->settings = get_option( 'wcml_exchange_rate_service_' . $this->id, array() );
38
 
39
+ $this->api_key = $this->get_setting( 'api-key' );
 
 
 
40
  }
41
 
42
  /**
90
  $this->save_settings();
91
  }
92
 
 
 
 
 
 
 
 
93
  /**
94
  * @param string $error_message
95
  */
compatibility/class-wcml-bookings.php CHANGED
@@ -203,6 +203,12 @@ class WCML_Bookings {
203
  add_action( 'woocommerce_booking_paid_to_cancelled_notification', array( $this, 'translate_booking_cancelled_admin_email_texts' ), 9 );
204
 
205
  add_filter( 'wcml_email_language', array( $this, 'booking_email_language' ) );
 
 
 
 
 
 
206
  }
207
 
208
  if ( ! is_admin() || isset( $_POST['action'] ) && $_POST['action'] == 'wc_bookings_calculate_costs' ) {
@@ -2546,4 +2552,49 @@ class WCML_Bookings {
2546
  return $product ? $product->get_type() === 'booking' : false;
2547
  }
2548
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2549
  }
203
  add_action( 'woocommerce_booking_paid_to_cancelled_notification', array( $this, 'translate_booking_cancelled_admin_email_texts' ), 9 );
204
 
205
  add_filter( 'wcml_email_language', array( $this, 'booking_email_language' ) );
206
+
207
+ if( $this->is_bookings_listing_page() ) {
208
+ $this->remove_language_switcher();
209
+ add_filter( 'wp_count_posts', array( $this, 'count_bookings_by_current_language' ), 10, 2 );
210
+ add_filter( 'views_edit-wc_booking', array( $this, 'unset_mine_from_bookings_views' ) );
211
+ }
212
  }
213
 
214
  if ( ! is_admin() || isset( $_POST['action'] ) && $_POST['action'] == 'wc_bookings_calculate_costs' ) {
2552
  return $product ? $product->get_type() === 'booking' : false;
2553
  }
2554
 
2555
+ /**
2556
+ * @param string $counts
2557
+ * @param string $type
2558
+ *
2559
+ * @return object
2560
+ */
2561
+ public function count_bookings_by_current_language( $counts, $type ) {
2562
+
2563
+ $query = "SELECT p.post_status, COUNT( * ) AS num_posts FROM {$this->wpdb->posts} as p
2564
+ LEFT JOIN {$this->wpdb->prefix}icl_translations as icl ON p.ID = icl.element_id
2565
+ WHERE p.post_type = %s AND icl.language_code = %s AND icl.element_type = %s GROUP BY p.post_status";
2566
+
2567
+ $results = $this->wpdb->get_results( $this->wpdb->prepare( $query, $type, $this->sitepress->get_current_language(), 'post_wc_booking' ), ARRAY_A );
2568
+ $counts = array_fill_keys( get_post_stati(), 0 );
2569
+
2570
+ foreach ( $results as $row ) {
2571
+ $counts[ $row['post_status'] ] = $row['num_posts'];
2572
+ }
2573
+
2574
+ $counts = (object) $counts;
2575
+
2576
+ return $counts;
2577
+ }
2578
+
2579
+ /**
2580
+ * @param array $views
2581
+ *
2582
+ * @return array
2583
+ */
2584
+ public function unset_mine_from_bookings_views( $views ) {
2585
+ unset( $views['mine'] );
2586
+
2587
+ return $views;
2588
+ }
2589
+
2590
+ public function remove_language_switcher() {
2591
+ remove_action( 'wp_before_admin_bar_render', array( $this->sitepress, 'admin_language_switcher' ) );
2592
+ }
2593
+
2594
+ /**
2595
+ * @return bool
2596
+ */
2597
+ private function is_bookings_listing_page() {
2598
+ return isset( $_GET['post_type'] ) && 'wc_booking' === $_GET['post_type'];
2599
+ }
2600
  }
compatibility/class-wcml-product-bundles.php CHANGED
@@ -62,9 +62,9 @@ class WCML_Product_Bundles {
62
  add_action( 'woocommerce_before_delete_bundled_item', array( $this, 'delete_bundled_item_relationship' ) );
63
  }
64
 
65
- // product bundle using separate custom fields for prices
66
  if ( wcml_is_multi_currency_on() ) {
67
- add_filter( 'wcml_price_custom_fields_filtered', array( $this, 'get_price_custom_fields' ) );
68
  add_filter( 'wcml_update_custom_prices_values', array( $this, 'update_bundles_custom_prices_values' ), 10, 2 );
69
  add_filter( 'wcml_after_save_custom_prices', array( $this, 'update_bundles_base_price' ), 10, 4 );
70
  }
@@ -849,4 +849,4 @@ class WCML_Product_Bundles {
849
 
850
  }
851
 
852
- }
62
  add_action( 'woocommerce_before_delete_bundled_item', array( $this, 'delete_bundled_item_relationship' ) );
63
  }
64
 
65
+ // product bundle using separate custom fields for prices.
66
  if ( wcml_is_multi_currency_on() ) {
67
+ add_filter( 'wcml_price_custom_fields_filtered', array( $this, 'get_price_custom_fields' ), 10, 2 );
68
  add_filter( 'wcml_update_custom_prices_values', array( $this, 'update_bundles_custom_prices_values' ), 10, 2 );
69
  add_filter( 'wcml_after_save_custom_prices', array( $this, 'update_bundles_base_price' ), 10, 4 );
70
  }
849
 
850
  }
851
 
852
+ }
compatibility/class-wcml-variation-swatches-and-photos.php CHANGED
@@ -1,62 +1,82 @@
1
  <?php
2
 
3
- class WCML_Variation_Swatches_and_Photos{
4
-
5
- function __construct(){
6
- add_action('wcml_after_duplicate_product_post_meta',array($this,'sync_variation_swatches_and_photos'),10,3);
7
- }
8
-
9
- function sync_variation_swatches_and_photos($original_product_id, $trnsl_product_id, $data = false){
10
- global $sitepress, $wpdb;
11
-
12
- $atts = maybe_unserialize(get_post_meta($original_product_id, '_swatch_type_options', true));
13
-
14
- if (!is_array($atts)) {
15
- return;
16
- }
17
-
18
- $lang = $sitepress->get_language_for_element($trnsl_product_id,'post_product');
19
- $tr_atts = $atts;
20
-
21
- $original_product_post = get_post($original_product_id);
22
-
23
- $original_product_taxonomies = get_object_taxonomies($original_product_post);
24
-
25
- $original_product_terms = get_terms($original_product_taxonomies);
26
-
27
- if (is_array($original_product_terms)) {
28
-
29
- foreach ($atts as $att_name=>$att_opts) {
30
-
31
- $attributes_hashed_names = array_keys($att_opts['attributes']);
32
-
33
- foreach($original_product_terms as $original_product_term) {
34
- $original_product_term_slug_md5 = md5($original_product_term->slug);
35
-
36
- if (in_array($original_product_term_slug_md5, $attributes_hashed_names)) {
37
-
38
- $translated_product_term_id = apply_filters('wpml_object_id', $original_product_term->term_id, $original_product_term->taxonomy, false, $lang);
39
-
40
- $translated_product_term = get_term($translated_product_term_id, $original_product_term->taxonomy);
41
-
42
- if (is_object($translated_product_term)) {
43
-
44
- $translated_product_term_slug_md5 = md5($translated_product_term->slug);
45
-
46
- $tr_atts[$att_name]['attributes'][$translated_product_term_slug_md5] = $tr_atts[$att_name]['attributes'][$original_product_term_slug_md5];
47
-
48
- unset( $tr_atts[$att_name]['attributes'][$original_product_term_slug_md5] );
49
- }
50
-
51
- }
52
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
  }
54
-
55
  }
56
-
57
  }
 
 
 
 
 
58
 
59
- update_post_meta($trnsl_product_id,'_swatch_type_options',$tr_atts); // Meta gets overwritten
60
- }
61
 
62
  }
1
  <?php
2
 
3
+ /**
4
+ * Compatibility class for Variation Swatches and Photos plugin
5
+ */
6
+ class WCML_Variation_Swatches_And_Photos {
7
+
8
+ /** @var SitePress */
9
+ private $sitepress;
10
+
11
+ function __construct( SitePress $sitepress ) {
12
+ $this->sitepress = $sitepress;
13
+ }
14
+
15
+ public function add_hooks() {
16
+ add_action( 'wcml_after_duplicate_product_post_meta', array(
17
+ $this,
18
+ 'sync_variation_swatches_and_photos'
19
+ ), 10, 3 );
20
+ }
21
+
22
+ /**
23
+ * Synchronize Variation Swatches and Photos
24
+ *
25
+ * @param int $original_product_id Original product ID.
26
+ * @param int $trnsl_product_id Translated product ID.
27
+ * @param array $data Product data.
28
+ */
29
+ public function sync_variation_swatches_and_photos( $original_product_id, $trnsl_product_id, $data = false ) {
30
+
31
+ $atts = maybe_unserialize( get_post_meta( $original_product_id, '_swatch_type_options', true ) );
32
+
33
+ if ( ! is_array( $atts ) ) {
34
+ return;
35
+ }
36
+
37
+ $lang = $this->sitepress->get_language_for_element( $trnsl_product_id, 'post_product' );
38
+ $tr_atts = $atts;
39
+
40
+ $original_product_post = get_post( $original_product_id );
41
+
42
+ $original_product_taxonomies = get_object_taxonomies( $original_product_post );
43
+
44
+ $original_product_terms = get_terms( $original_product_taxonomies );
45
+
46
+ if ( is_array( $original_product_terms ) ) {
47
+
48
+ remove_filter( 'get_term', array( $this->sitepress, 'get_term_adjust_id' ), 1 );
49
+
50
+ foreach ( $atts as $att_name => $att_opts ) {
51
+
52
+ $attributes_hashed_names = array_keys( $att_opts['attributes'] );
53
+
54
+ foreach ( $original_product_terms as $original_product_term ) {
55
+ $original_product_term_slug_md5 = md5( $original_product_term->slug );
56
+
57
+ if ( in_array( $original_product_term_slug_md5, $attributes_hashed_names, true ) ) {
58
+
59
+ $translated_product_term_id = apply_filters( 'wpml_object_id', $original_product_term->term_id, $original_product_term->taxonomy, false, $lang );
60
+
61
+ $translated_product_term = get_term( $translated_product_term_id, $original_product_term->taxonomy );
62
+
63
+ if ( is_object( $translated_product_term ) ) {
64
+
65
+ $translated_product_term_slug_md5 = md5( $translated_product_term->slug );
66
+
67
+ $tr_atts[ $att_name ]['attributes'][ $translated_product_term_slug_md5 ] = $tr_atts[ $att_name ]['attributes'][ $original_product_term_slug_md5 ];
68
+
69
+ unset( $tr_atts[ $att_name ]['attributes'][ $original_product_term_slug_md5 ] );
70
  }
 
71
  }
 
72
  }
73
+ }
74
+
75
+ add_filter( 'get_term', array( $this->sitepress, 'get_term_adjust_id' ), 1, 1 );
76
+
77
+ }
78
 
79
+ update_post_meta( $trnsl_product_id, '_swatch_type_options', $tr_atts ); // Meta gets overwritten.
80
+ }
81
 
82
  }
compatibility/class-wcml-yikes-custom-product-tabs-pro.php ADDED
@@ -0,0 +1,265 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class WCML_YIKES_Custom_Product_Tabs_Pro
5
+ */
6
+ class WCML_YIKES_Custom_Product_Tabs_Pro {
7
+
8
+ const CUSTOM_TABS_FIELD = 'yikes_woo_products_tabs';
9
+
10
+ /**
11
+ * @var WPML_Element_Translation_Package
12
+ */
13
+ private $tp;
14
+
15
+ /**
16
+ * @var SitePress
17
+ */
18
+ private $sitepress;
19
+
20
+ /**
21
+ * @var woocommerce_wpml
22
+ */
23
+ private $woocommerce_wpml;
24
+
25
+ /**
26
+ * WCML_Tab_Manager constructor.
27
+ *
28
+ * @param woocommerce_wpml $woocommerce_wpml
29
+ * @param SitePress $sitepress
30
+ * @param WPML_Element_Translation_Package $tp
31
+ */
32
+ function __construct( woocommerce_wpml $woocommerce_wpml, SitePress $sitepress, WPML_Element_Translation_Package $tp ) {
33
+ $this->sitepress = $sitepress;
34
+ $this->woocommerce_wpml = $woocommerce_wpml;
35
+ $this->tp = $tp;
36
+ }
37
+
38
+ public function add_hooks() {
39
+
40
+ if ( is_admin() ) {
41
+ add_action( 'wcml_gui_additional_box_html', array( $this, 'custom_box_html' ), 10, 3 );
42
+ add_filter( 'wcml_gui_additional_box_data', array( $this, 'custom_box_html_data' ), 10, 4 );
43
+ add_action( 'wcml_update_extra_fields', array( $this, 'sync_tabs' ), 10, 4 );
44
+ add_filter( 'wpml_duplicate_custom_fields_exceptions', array( $this, 'custom_fields_exceptions' ) );
45
+ add_filter( 'wcml_do_not_display_custom_fields_for_product', array( $this, 'custom_fields_exceptions' ) );
46
+
47
+ add_filter( 'wpml_tm_translation_job_data', array( $this, 'append_custom_tabs_to_translation_package' ), 10, 2 );
48
+ add_action( 'wpml_translation_job_saved', array( $this, 'save_custom_tabs_translation' ), 10, 3 );
49
+
50
+ add_action( 'woocommerce_product_data_panels', array( $this, 'show_pointer_info' ) );
51
+ add_action( 'init', array( $this, 'maybe_remove_admin_language_switcher' ) );
52
+ }
53
+ }
54
+
55
+ /**
56
+ * @param object $obj
57
+ * @param int $product_id
58
+ * @param array $data
59
+ *
60
+ */
61
+ function custom_box_html( $obj, $product_id, $data ) {
62
+
63
+ $orig_prod_tabs = $this->get_product_tabs( $product_id );
64
+
65
+ if ( $orig_prod_tabs ) {
66
+ $tabs_section = new WPML_Editor_UI_Field_Section( __( 'Custom Tabs', 'woocommerce-multilingual' ) );
67
+
68
+ $keys = array_keys( $orig_prod_tabs );
69
+ $last_key = end( $keys );
70
+ $divider = true;
71
+
72
+ foreach ( $orig_prod_tabs as $key => $prod_tab ) {
73
+ if ( $key === $last_key ) {
74
+ $divider = false;
75
+ }
76
+ $group = new WPML_Editor_UI_Field_Group( '', $divider );
77
+ $tab_field = new WPML_Editor_UI_Single_Line_Field( 'tab_' . $key . '_title', __( 'Tab Title', 'woocommerce-multilingual' ), $data, false );
78
+ $group->add_field( $tab_field );
79
+ $tab_field = new WCML_Editor_UI_WYSIWYG_Field( 'tab_' . $key . '_content', null, $data, false );
80
+ $group->add_field( $tab_field );
81
+ $tabs_section->add_field( $group );
82
+ }
83
+
84
+ $obj->add_field( $tabs_section );
85
+ }
86
+ }
87
+
88
+
89
+ /**
90
+ * @param array $data
91
+ * @param int $product_id
92
+ * @param object $translation
93
+ * @param string $lang
94
+ *
95
+ * @return array
96
+ */
97
+ function custom_box_html_data( $data, $product_id, $translation, $lang ) {
98
+
99
+ $orig_prod_tabs = $this->get_product_tabs( $product_id );
100
+ if ( $orig_prod_tabs ) {
101
+ foreach ( $orig_prod_tabs as $key => $prod_tab ) {
102
+ if ( isset( $prod_tab['title'] ) ) {
103
+ $data[ 'tab_' . $key . '_title' ] = array( 'original' => $prod_tab['title'] );
104
+ }
105
+ if ( isset( $prod_tab['content'] ) ) {
106
+ $data[ 'tab_' . $key . '_content' ] = array( 'original' => $prod_tab['content'] );
107
+ }
108
+ }
109
+
110
+ if ( $translation ) {
111
+ $tr_prod_tabs = $this->get_product_tabs( $translation->ID );
112
+ if ( $tr_prod_tabs ) {
113
+ foreach ( $tr_prod_tabs as $key => $prod_tab ) {
114
+ if ( isset( $prod_tab['title'] ) ) {
115
+ $data[ 'tab_' . $key . '_title' ]['translation'] = $prod_tab['title'];
116
+ }
117
+ if ( isset( $prod_tab['content'] ) ) {
118
+ $data[ 'tab_' . $key . '_content' ]['translation'] = $prod_tab['content'];
119
+ }
120
+ }
121
+ }
122
+ }
123
+ }
124
+
125
+ return $data;
126
+ }
127
+
128
+ /**
129
+ * @param int $original_product_id
130
+ * @param int $trnsl_product_id
131
+ * @param array $data
132
+ * @param string $lang
133
+ *
134
+ */
135
+ function sync_tabs( $original_product_id, $trnsl_product_id, $data, $lang ) {
136
+
137
+ $orig_prod_tabs = $this->get_product_tabs( $original_product_id );
138
+
139
+ if ( ( isset( $_POST['icl_ajx_action'] ) && ( 'make_duplicates' === $_POST['icl_ajx_action'] ) ) || ( get_post_meta( $trnsl_product_id, '_icl_lang_duplicate_of', true ) ) ) {
140
+ update_post_meta( $trnsl_product_id, self::CUSTOM_TABS_FIELD, $orig_prod_tabs );
141
+ } elseif ( $orig_prod_tabs ) {
142
+ $trnsl_product_tabs = array();
143
+ foreach ( $orig_prod_tabs as $key => $orig_prod_tab ) {
144
+ $title_key = md5( 'tab_' . $key . '_title' );
145
+ $content_key = md5( 'tab_' . $key . '_content' );
146
+ $trnsl_product_tabs[ $key ]['id'] = $orig_prod_tab['id'];
147
+ $trnsl_product_tabs[ $key ]['title'] = isset( $data[ $title_key ] ) ? sanitize_text_field( $data[ $title_key ] ) : '';
148
+ $trnsl_product_tabs[ $key ]['content'] = isset( $data[ $content_key ] ) ? wp_kses_post( $data[ $content_key ] ) : '';
149
+ }
150
+ update_post_meta( $trnsl_product_id, self::CUSTOM_TABS_FIELD, $trnsl_product_tabs );
151
+ }
152
+ }
153
+
154
+ /**
155
+ * @param int $product_id
156
+ *
157
+ * @return array
158
+ */
159
+ private function get_product_tabs( $product_id ) {
160
+ return (array) get_post_meta( $product_id, self::CUSTOM_TABS_FIELD, true );
161
+ }
162
+
163
+
164
+ /**
165
+ * @param array $fields
166
+ *
167
+ * @return array
168
+ */
169
+ public function custom_fields_exceptions( $fields ) {
170
+ $fields[] = self::CUSTOM_TABS_FIELD;
171
+ return $fields;
172
+ }
173
+
174
+ /**
175
+ * @param array $package
176
+ * @param object $post
177
+ *
178
+ * @return array
179
+ */
180
+ public function append_custom_tabs_to_translation_package( $package, $post ) {
181
+
182
+ if ( 'product' === $post->post_type ) {
183
+
184
+ $orig_prod_tabs = $this->get_product_tabs( $post->ID );
185
+ if ( $orig_prod_tabs ) {
186
+ foreach ( $orig_prod_tabs as $key => $prod_tab ) {
187
+ if ( isset( $prod_tab['title'] ) ) {
188
+ $package['contents'][ self::CUSTOM_TABS_FIELD . ':product_tab:' . $key . ':title' ] = array(
189
+ 'translate' => 1,
190
+ 'data' => $this->tp->encode_field_data( $prod_tab['title'], 'base64' ),
191
+ 'format' => 'base64',
192
+ );
193
+ }
194
+
195
+ if ( isset( $prod_tab['content'] ) ) {
196
+ $package['contents'][ self::CUSTOM_TABS_FIELD . ':product_tab:' . $key . ':content' ] = array(
197
+ 'translate' => 1,
198
+ 'data' => $this->tp->encode_field_data( $prod_tab['content'], 'base64' ),
199
+ 'format' => 'base64',
200
+ );
201
+ }
202
+ }
203
+ }
204
+ }
205
+
206
+ return $package;
207
+ }
208
+
209
+ /**
210
+ * @param int $post_id
211
+ * @param array $data
212
+ * @param object $job
213
+ */
214
+ public function save_custom_tabs_translation( $post_id, $data, $job ) {
215
+
216
+ $original_product_tabs = $this->get_product_tabs( $job->original_doc_id );
217
+
218
+ if ( $original_product_tabs ) {
219
+
220
+ $translated_product_tabs = $this->get_product_tabs( $post_id );
221
+
222
+ if( !$translated_product_tabs ){
223
+ $translated_product_tabs = $original_product_tabs;
224
+ }
225
+
226
+ foreach ( $data as $value ) {
227
+
228
+ if ( preg_match( '/'.self::CUSTOM_TABS_FIELD.':product_tab:([0-9]+):(.+)/', $value['field_type'], $matches ) ) {
229
+
230
+ $tab_key = $matches[1];
231
+ $field = $matches[2];
232
+
233
+ $translated_product_tabs[ $tab_key ][ $field ] = 'title' === $field ? sanitize_text_field( $value['data'] ) : wp_kses_post( $value['data'] );
234
+ }
235
+ }
236
+
237
+ update_post_meta( $post_id, self::CUSTOM_TABS_FIELD, $translated_product_tabs );
238
+ }
239
+ }
240
+
241
+ public function show_pointer_info() {
242
+
243
+ $a = __( 'You can translate your custom product tabs on the %s', 'woocommerce-multilingual' );
244
+ $b = __( 'WooCommerce product translation page', 'woocommerce-multilingual' );
245
+ $link = '<a href="' . admin_url( 'admin.php?page=wpml-wcml' ) . '">' . $b . '</a>';
246
+
247
+ $pointer_ui = new WCML_Pointer_UI(
248
+ sprintf( $a, $link ),
249
+ 'https://wpml.org/documentation/woocommerce-extensions-compatibility/',
250
+ 'yikes_woocommerce_custom_product_tabs',
251
+ 'prepend'
252
+ );
253
+
254
+ $pointer_ui->show();
255
+ }
256
+
257
+ public function maybe_remove_admin_language_switcher( ) {
258
+
259
+ if ( isset( $_GET['page'] ) && 'yikes-woo-settings' === $_GET['page'] ) {
260
+ remove_action( 'wp_before_admin_bar_render', array( $this->sitepress, 'admin_language_switcher' ) );
261
+ }
262
+
263
+ }
264
+
265
+ }
inc/admin-menus/class-wcml-admin-menus.php CHANGED
@@ -121,8 +121,13 @@ class WCML_Admin_Menus{
121
  public static function documentation_links() {
122
  global $post, $pagenow;
123
 
124
- if ( is_null( $post ) )
125
- return;
 
 
 
 
 
126
 
127
  $tracking_link = new WCML_Tracking_Link();
128
 
121
  public static function documentation_links() {
122
  global $post, $pagenow;
123
 
124
+ if ( $post && ! is_object( $post ) ) {
125
+ $post = get_post( $post );
126
+ }
127
+
128
+ if ( ! $post ) {
129
+ return;
130
+ }
131
 
132
  $tracking_link = new WCML_Tracking_Link();
133
 
inc/class-wcml-attributes.php CHANGED
@@ -308,11 +308,12 @@ class WCML_Attributes{
308
  if ( substr( $attribute, 0, 3 ) == 'pa_' ) {
309
  //attr is taxonomy
310
  if( $this->is_translatable_attribute( $attribute ) ){
311
- $default_term_id = $this->woocommerce_wpml->terms->wcml_get_term_id_by_slug( $attribute, $default_term_slug );
312
- $tr_id = apply_filters( 'translate_object_id', $default_term_id, $attribute, false, $lang );
 
313
 
314
  if( $tr_id ){
315
- $translated_term = $this->woocommerce_wpml->terms->wcml_get_term_by_id( $tr_id, $attribute );
316
  $unserialized_default_attributes[ $attribute ] = $translated_term->slug;
317
  }
318
  }else{
308
  if ( substr( $attribute, 0, 3 ) == 'pa_' ) {
309
  //attr is taxonomy
310
  if( $this->is_translatable_attribute( $attribute ) ){
311
+ $sanitized_attribute_name = wc_sanitize_taxonomy_name( $attribute );
312
+ $default_term_id = $this->woocommerce_wpml->terms->wcml_get_term_id_by_slug( $sanitized_attribute_name, $default_term_slug );
313
+ $tr_id = apply_filters( 'translate_object_id', $default_term_id, $sanitized_attribute_name, false, $lang );
314
 
315
  if( $tr_id ){
316
+ $translated_term = $this->woocommerce_wpml->terms->wcml_get_term_by_id( $tr_id, $sanitized_attribute_name );
317
  $unserialized_default_attributes[ $attribute ] = $translated_term->slug;
318
  }
319
  }else{
inc/class-wcml-comments.php CHANGED
@@ -78,7 +78,9 @@ class WCML_Comments {
78
  }
79
  }
80
 
81
- $reviews_count += $review_count;
 
 
82
  }
83
 
84
  if ( $average_ratings_sum ) {
78
  }
79
  }
80
 
81
+ if( $review_count ){
82
+ $reviews_count += $review_count;
83
+ }
84
  }
85
 
86
  if ( $average_ratings_sum ) {
inc/class-wcml-compatibility.php CHANGED
@@ -69,7 +69,8 @@ class WCML_Compatibility {
69
 
70
  // WooCommerce Variation Swatches and Photos
71
  if ( class_exists( 'WC_SwatchesPlugin' ) ) {
72
- $this->variation_sp = new WCML_Variation_Swatches_and_Photos();
 
73
  }
74
 
75
  // Product Add-ons
@@ -267,6 +268,12 @@ class WCML_Compatibility {
267
  $this->wc_type_column->add_hooks();
268
  }
269
 
 
 
 
 
 
 
270
  }
271
 
272
  }
69
 
70
  // WooCommerce Variation Swatches and Photos
71
  if ( class_exists( 'WC_SwatchesPlugin' ) ) {
72
+ $this->variation_sp = new WCML_Variation_Swatches_And_Photos( $this->sitepress );
73
+ $this->variation_sp->add_hooks();
74
  }
75
 
76
  // Product Add-ons
268
  $this->wc_type_column->add_hooks();
269
  }
270
 
271
+ // Custom Product Tabs PRO
272
+ if ( class_exists( 'YIKES_Custom_Product_Tabs_Pro' ) ) {
273
+ $this->custom_product_tabs = new WCML_YIKES_Custom_Product_Tabs_Pro( $this->woocommerce_wpml, $this->sitepress, $this->tp );
274
+ $this->custom_product_tabs->add_hooks();
275
+ }
276
+
277
  }
278
 
279
  }
inc/class-wcml-emails.php CHANGED
@@ -47,10 +47,14 @@ class WCML_Emails{
47
  $this,
48
  'email_heading_processing'
49
  ), 9 );
50
- add_action( 'woocommerce_order_status_pending_to_on-hold_notification', array(
51
- $this,
52
- 'email_heading_processing'
53
- ), 9 );
 
 
 
 
54
 
55
  //wrappers for email's body
56
  add_action( 'woocommerce_before_resend_order_emails', array( $this, 'email_header' ) );
@@ -71,31 +75,15 @@ class WCML_Emails{
71
  ), 9 );
72
  add_action( 'woocommerce_new_customer_note', array( $this, 'refresh_email_lang' ), 9 );
73
 
74
- //new order admins email
75
- add_action( 'woocommerce_order_status_pending_to_processing_notification', array(
76
- $this,
77
- 'new_order_admin_email'
78
- ), 9 );
79
- add_action( 'woocommerce_order_status_pending_to_completed_notification', array(
80
- $this,
81
- 'new_order_admin_email'
82
- ), 9 );
83
- add_action( 'woocommerce_order_status_pending_to_on-hold_notification', array(
84
- $this,
85
- 'new_order_admin_email'
86
- ), 9 );
87
- add_action( 'woocommerce_order_status_failed_to_processing_notification', array(
88
- $this,
89
- 'new_order_admin_email'
90
- ), 9 );
91
- add_action( 'woocommerce_order_status_failed_to_completed_notification', array(
92
- $this,
93
- 'new_order_admin_email'
94
- ), 9 );
95
- add_action( 'woocommerce_order_status_failed_to_on-hold_notification', array(
96
- $this,
97
- 'new_order_admin_email'
98
- ), 9 );
99
  add_action( 'woocommerce_before_resend_order_emails', array( $this, 'backend_new_order_admin_email' ), 9 );
100
 
101
  add_filter( 'icl_st_admin_string_return_cached', array( $this, 'admin_string_return_cached' ), 10, 2 );
@@ -138,6 +126,9 @@ class WCML_Emails{
138
 
139
  add_filter( 'woocommerce_email_heading_new_order', array( $this, 'new_order_email_heading' ) );
140
  add_filter( 'woocommerce_email_subject_new_order', array( $this, 'new_order_email_subject' ) );
 
 
 
141
  }
142
 
143
  function email_refresh_in_ajax() {
@@ -231,19 +222,36 @@ class WCML_Emails{
231
  }
232
 
233
  function email_heading_processing($order_id){
 
 
234
 
235
- if( class_exists( 'WC_Email_Customer_Processing_Order' ) && isset( $this->woocommerce->mailer()->emails[ 'WC_Email_Customer_Processing_Order' ] ) ){
 
 
236
 
237
- $this->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 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
238
 
239
- $this->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 );
240
- $enabled = $this->woocommerce->mailer()->emails['WC_Email_Customer_Processing_Order']->enabled;
241
- $this->woocommerce->mailer()->emails['WC_Email_Customer_Processing_Order']->enabled = false;
242
- $this->woocommerce->mailer()->emails['WC_Email_Customer_Processing_Order']->trigger($order_id);
243
- $this->woocommerce->mailer()->emails['WC_Email_Customer_Processing_Order']->enabled = $enabled;
244
 
245
- }
246
- }
 
247
 
248
  function email_heading_note($args){
249
 
@@ -304,21 +312,30 @@ class WCML_Emails{
304
  }
305
 
306
  public function new_order_email_heading( $heading ){
307
- $translated_heading = $this->woocommerce->mailer()->emails['WC_Email_New_Order']->heading;
308
- if( $translated_heading ){
309
- $heading = $this->woocommerce->mailer()->emails['WC_Email_New_Order']->format_string( $translated_heading );
310
- }
311
-
312
- return $heading;
313
  }
314
 
315
  public function new_order_email_subject( $subject ){
316
- $translated_subject = $this->woocommerce->mailer()->emails['WC_Email_New_Order']->subject;
317
- if( $translated_subject ){
318
- $subject = $this->woocommerce->mailer()->emails['WC_Email_New_Order']->format_string( $translated_subject );
319
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
320
 
321
- return $subject;
322
  }
323
 
324
  public function backend_new_order_admin_email( $order_id ){
47
  $this,
48
  'email_heading_processing'
49
  ), 9 );
50
+
51
+
52
+ foreach( array( 'pending', 'failed', 'cancelled' ) as $state ) {
53
+ add_action( 'woocommerce_order_status_' . $state . '_to_on-hold_notification', array(
54
+ $this,
55
+ 'email_heading_on_hold'
56
+ ), 9 );
57
+ }
58
 
59
  //wrappers for email's body
60
  add_action( 'woocommerce_before_resend_order_emails', array( $this, 'email_header' ) );
75
  ), 9 );
76
  add_action( 'woocommerce_new_customer_note', array( $this, 'refresh_email_lang' ), 9 );
77
 
78
+ foreach( array( 'pending', 'failed' ) as $from_state ) {
79
+ foreach ( array( 'processing', 'completed', 'on-hold' ) as $to_state ) {
80
+ add_action( 'woocommerce_order_status_'.$from_state.'_to_'.$to_state.'_notification', array(
81
+ $this,
82
+ 'new_order_admin_email'
83
+ ), 9 );
84
+ }
85
+ }
86
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  add_action( 'woocommerce_before_resend_order_emails', array( $this, 'backend_new_order_admin_email' ), 9 );
88
 
89
  add_filter( 'icl_st_admin_string_return_cached', array( $this, 'admin_string_return_cached' ), 10, 2 );
126
 
127
  add_filter( 'woocommerce_email_heading_new_order', array( $this, 'new_order_email_heading' ) );
128
  add_filter( 'woocommerce_email_subject_new_order', array( $this, 'new_order_email_subject' ) );
129
+
130
+ add_filter( 'woocommerce_email_heading_customer_on_hold_order', array( $this, 'customer_on_hold_order_heading' ) );
131
+ add_filter( 'woocommerce_email_subject_customer_on_hold_order', array( $this, 'customer_on_hold_order_subject' ) );
132
  }
133
 
134
  function email_refresh_in_ajax() {
222
  }
223
 
224
  function email_heading_processing($order_id){
225
+ $this->translate_email_headings( $order_id, 'WC_Email_Customer_Processing_Order', 'woocommerce_customer_processing_order_settings' );
226
+ }
227
 
228
+ public function email_heading_on_hold( $order_id ){
229
+ $this->translate_email_headings( $order_id, 'WC_Email_Customer_On_Hold_Order', 'woocommerce_customer_on_hold_order_settings' );
230
+ }
231
 
232
+ /**
233
+ * @param int|string $order_id
234
+ * @param string $class_name
235
+ * @param string $string_name
236
+ */
237
+ private function translate_email_headings( $order_id, $class_name, $string_name ){
238
+ if( class_exists( $class_name ) && isset( $this->woocommerce->mailer()->emails[ $class_name ] ) ){
239
+ $this->woocommerce->mailer()->emails[ $class_name ]->heading = $this->wcml_get_translated_email_string( 'admin_texts_'.$string_name, '['.$string_name.']heading', $order_id );
240
+ $this->woocommerce->mailer()->emails[ $class_name ]->subject = $this->wcml_get_translated_email_string( 'admin_texts_'.$string_name, '['.$string_name.']subject', $order_id );
241
+ $enabled = $this->woocommerce->mailer()->emails[ $class_name ]->enabled;
242
+ $this->woocommerce->mailer()->emails[ $class_name ]->enabled = false;
243
+ $this->woocommerce->mailer()->emails[ $class_name ]->trigger($order_id);
244
+ $this->woocommerce->mailer()->emails[ $class_name ]->enabled = $enabled;
245
+ }
246
+ }
247
 
248
+ public function customer_on_hold_order_heading( $heading ){
249
+ return $this->get_translated_order_strings( 'heading', $heading, 'WC_Email_Customer_On_Hold_Order' );
250
+ }
 
 
251
 
252
+ public function customer_on_hold_order_subject( $subject ){
253
+ return $this->get_translated_order_strings( 'subject', $subject, 'WC_Email_Customer_On_Hold_Order' );
254
+ }
255
 
256
  function email_heading_note($args){
257
 
312
  }
313
 
314
  public function new_order_email_heading( $heading ){
315
+ return $this->get_translated_order_strings( 'heading', $heading, 'WC_Email_New_Order' );
 
 
 
 
 
316
  }
317
 
318
  public function new_order_email_subject( $subject ){
319
+ return $this->get_translated_order_strings( 'subject', $subject, 'WC_Email_New_Order' );
320
+ }
321
+
322
+ /**
323
+ * @param string $type
324
+ * @param string $string
325
+ * @param string $class_name
326
+ *
327
+ * @return string
328
+ */
329
+ private function get_translated_order_strings( $type, $string, $class_name ){
330
+ if( 'heading' === $type ){
331
+ $translated_string = $this->woocommerce->mailer()->emails[ $class_name ]->heading;
332
+ }elseif( 'subject' === $type ){
333
+ $translated_string = $this->woocommerce->mailer()->emails[ $class_name ]->subject;
334
+ }else{
335
+ return $string;
336
+ }
337
 
338
+ return $translated_string ? $this->woocommerce->mailer()->emails[ $class_name ]->format_string( $translated_string ): $string;
339
  }
340
 
341
  public function backend_new_order_admin_email( $order_id ){
inc/class-wcml-media.php CHANGED
@@ -94,10 +94,11 @@ class WCML_Media{
94
  $media_duplicate = $factory->create();
95
  $translated_thumbnail = $media_duplicate->create_duplicate_attachment( $thumbnail_id, wp_get_post_parent_id( $thumbnail_id ), $lang );
96
  }
97
-
98
- update_post_meta( $translated_variation_id, '_thumbnail_id', $translated_thumbnail );
99
- update_post_meta( $variation_id, '_wpml_media_duplicate', 1 );
100
- update_post_meta( $variation_id, '_wpml_media_featured', 1 );
 
101
  }
102
 
103
 
94
  $media_duplicate = $factory->create();
95
  $translated_thumbnail = $media_duplicate->create_duplicate_attachment( $thumbnail_id, wp_get_post_parent_id( $thumbnail_id ), $lang );
96
  }
97
+ if( $translated_thumbnail ) {
98
+ update_post_meta( $translated_variation_id, '_thumbnail_id', $translated_thumbnail );
99
+ update_post_meta( $variation_id, '_wpml_media_duplicate', 1 );
100
+ update_post_meta( $variation_id, '_wpml_media_featured', 1 );
101
+ }
102
  }
103
 
104
 
inc/class-wcml-orders.php CHANGED
@@ -35,7 +35,6 @@ class WCML_Orders {
35
 
36
  function init(){
37
 
38
- add_action('woocommerce_shipping_update_ajax', array($this, 'fix_shipping_update'));
39
  add_action('woocommerce_checkout_update_order_meta', array($this, 'set_order_language'));
40
 
41
  add_filter('icl_lang_sel_copy_parameters', array($this, 'append_query_parameters'));
@@ -270,36 +269,16 @@ class WCML_Orders {
270
  }
271
  }
272
 
273
- // Fix for shipping update on the checkout page.
274
- function fix_shipping_update($amount){
275
- global $sitepress, $post;
276
-
277
- if($sitepress->get_current_language() !== $sitepress->get_default_language() && $post->ID == $this->checkout_page_id()){
278
-
279
- $_SESSION['icl_checkout_shipping_amount'] = $amount;
280
-
281
- $amount = $_SESSION['icl_checkout_shipping_amount'];
282
-
283
- }
284
-
285
- return $amount;
286
- }
287
-
288
-
289
  /**
290
  * Adds language to order post type.
291
  *
292
- * Language was stored in the session created on checkout page.
293
- * See params().
294
- *
295
  * @param type $order_id
296
  */
297
- function set_order_language($order_id) {
298
- if(!get_post_meta($order_id, 'wpml_language')){
299
- $language = isset($_SESSION['wpml_globalcart_language']) ? $_SESSION['wpml_globalcart_language'] : ICL_LANGUAGE_CODE;
300
- update_post_meta($order_id, 'wpml_language', $language);
301
- }
302
- }
303
 
304
  function append_query_parameters($parameters){
305
 
35
 
36
  function init(){
37
 
 
38
  add_action('woocommerce_checkout_update_order_meta', array($this, 'set_order_language'));
39
 
40
  add_filter('icl_lang_sel_copy_parameters', array($this, 'append_query_parameters'));
269
  }
270
  }
271
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
272
  /**
273
  * Adds language to order post type.
274
  *
 
 
 
275
  * @param type $order_id
276
  */
277
+ function set_order_language( $order_id ) {
278
+ if ( ! get_post_meta( $order_id, 'wpml_language' ) ) {
279
+ update_post_meta( $order_id, 'wpml_language', ICL_LANGUAGE_CODE );
280
+ }
281
+ }
 
282
 
283
  function append_query_parameters($parameters){
284
 
inc/class-wcml-products.php CHANGED
@@ -49,6 +49,7 @@ class WCML_Products{
49
  } else {
50
  add_filter( 'woocommerce_json_search_found_products', array( $this, 'filter_found_products_by_language' ) );
51
  add_filter( 'woocommerce_related_products_args', array( $this, 'filter_related_products_args' ) );
 
52
  add_filter( 'woocommerce_shortcode_products_query', array(
53
  $this,
54
  'add_lang_to_shortcode_products_query'
@@ -72,6 +73,10 @@ class WCML_Products{
72
  add_filter( 'get_product_search_form', array( $this->sitepress, 'get_search_form_filter' ) );
73
 
74
  add_filter( 'woocommerce_pre_customer_bought_product', array( $this, 'is_customer_bought_product' ), 10, 4 );
 
 
 
 
75
  }
76
 
77
  /**
@@ -204,7 +209,7 @@ class WCML_Products{
204
  if( isset( $product_translations[ $language[ 'code' ] ] ) ) {
205
  $job_id = $this->wpdb->get_var(
206
  $this->wpdb->prepare(
207
- "SELECT tj.job_id FROM {$this->wpdb->prefix}icl_translate_job AS tj
208
  LEFT JOIN {$this->wpdb->prefix}icl_translation_status AS ts
209
  ON tj.rid = ts.rid WHERE ts.translation_id=%d",
210
  $product_translations[ $language[ 'code' ] ]->translation_id )
@@ -246,6 +251,8 @@ class WCML_Products{
246
  wpml_tm_load_status_display_filter();
247
  } ?>
248
  <a href="<?php echo apply_filters( 'wpml_link_to_translation', '', $original_product_id, $language[ 'code' ], $trid ) ?>"
 
 
249
  <?php if( isset( $product_translations[ $language[ 'code' ] ] ) ){
250
  $tr_status = $this->wpdb->get_row(
251
  $this->wpdb->prepare(
@@ -458,6 +465,19 @@ class WCML_Products{
458
  return $args;
459
  }
460
 
 
 
 
 
 
 
 
 
 
 
 
 
 
461
  /*
462
  * get meta ids for multiple values post meta key
463
  */
@@ -507,9 +527,10 @@ class WCML_Products{
507
  }elseif( isset( $_GET[ 'job_id' ] ) ){
508
 
509
  $job = $iclTranslationManagement->get_translation_job( $_GET[ 'job_id' ] );
510
- $from_lang = $job->source_language_code;
511
- $to_lang = $job->language_code;
512
-
 
513
  }
514
 
515
  if( isset( $from_lang ) ){
@@ -650,4 +671,45 @@ class WCML_Products{
650
  return $value;
651
  }
652
 
653
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
  } else {
50
  add_filter( 'woocommerce_json_search_found_products', array( $this, 'filter_found_products_by_language' ) );
51
  add_filter( 'woocommerce_related_products_args', array( $this, 'filter_related_products_args' ) );
52
+ add_filter( 'woocommerce_product_related_posts_query', array( $this, 'filter_related_products_query' ) );
53
  add_filter( 'woocommerce_shortcode_products_query', array(
54
  $this,
55
  'add_lang_to_shortcode_products_query'
73
  add_filter( 'get_product_search_form', array( $this->sitepress, 'get_search_form_filter' ) );
74
 
75
  add_filter( 'woocommerce_pre_customer_bought_product', array( $this, 'is_customer_bought_product' ), 10, 4 );
76
+
77
+ if ( $this->sitepress->get_wp_api()->version_compare( $this->sitepress->get_wp_api()->constant( 'WC_VERSION' ), '3.6.0', '>=' ) ) {
78
+ add_filter( 'get_post_metadata', array( $this, 'filter_product_data' ), 10, 3 );
79
+ }
80
  }
81
 
82
  /**
209
  if( isset( $product_translations[ $language[ 'code' ] ] ) ) {
210
  $job_id = $this->wpdb->get_var(
211
  $this->wpdb->prepare(
212
+ "SELECT MAX(tj.job_id) FROM {$this->wpdb->prefix}icl_translate_job AS tj
213
  LEFT JOIN {$this->wpdb->prefix}icl_translation_status AS ts
214
  ON tj.rid = ts.rid WHERE ts.translation_id=%d",
215
  $product_translations[ $language[ 'code' ] ]->translation_id )
251
  wpml_tm_load_status_display_filter();
252
  } ?>
253
  <a href="<?php echo apply_filters( 'wpml_link_to_translation', '', $original_product_id, $language[ 'code' ], $trid ) ?>"
254
+ class="js-wpml-translate-link"
255
+ data-tm-job-id="<?php echo $job_id ?>"
256
  <?php if( isset( $product_translations[ $language[ 'code' ] ] ) ){
257
  $tr_status = $this->wpdb->get_row(
258
  $this->wpdb->prepare(
465
  return $args;
466
  }
467
 
468
+ /**
469
+ * @param array $query
470
+ *
471
+ * @return array
472
+ */
473
+ public function filter_related_products_query( $query ) {
474
+
475
+ $query['join'] .= " LEFT JOIN {$this->wpdb->prefix}icl_translations AS icl ON icl.element_id = p.ID ";
476
+ $query['where'] .= $this->wpdb->prepare( " AND icl.language_code = %s ", $this->sitepress->get_current_language() );
477
+
478
+ return $query;
479
+ }
480
+
481
  /*
482
  * get meta ids for multiple values post meta key
483
  */
527
  }elseif( isset( $_GET[ 'job_id' ] ) ){
528
 
529
  $job = $iclTranslationManagement->get_translation_job( $_GET[ 'job_id' ] );
530
+ if( $job ){
531
+ $from_lang = $job->source_language_code;
532
+ $to_lang = $job->language_code;
533
+ }
534
  }
535
 
536
  if( isset( $from_lang ) ){
671
  return $value;
672
  }
673
 
674
+
675
+ public function filter_product_data( $data, $product_id, $meta_key ) {
676
+
677
+ if ( ! $meta_key && in_array( get_post_type( $product_id ), array( 'product', 'product_variation' ) ) ) {
678
+ remove_filter( 'get_post_metadata', array( $this, 'filter_product_data' ), 10 );
679
+
680
+ $data = get_post_meta( $product_id );
681
+
682
+ $is_mc_enabled = (int) $this->woocommerce_wpml->settings['enable_multi_currency'] === (int) $this->sitepress->get_wp_api()->constant( 'WCML_MULTI_CURRENCIES_INDEPENDENT' );
683
+
684
+ if ( $is_mc_enabled ) {
685
+ $price_keys = wcml_price_custom_fields( $product_id );
686
+ }
687
+
688
+ foreach ( $data as $meta_key => $meta_value ) {
689
+
690
+ $filtered_value = false;
691
+
692
+ if ( $is_mc_enabled && in_array( $meta_key, $price_keys, true ) ) {
693
+ $filtered_value = $this->woocommerce_wpml->multi_currency->prices->product_price_filter( null, $product_id, $meta_key, true );
694
+ } elseif ( in_array( $meta_key, array( '_wc_review_count', '_wc_average_rating' ), true ) ) {
695
+ $filtered_value = $this->woocommerce_wpml->comments->filter_average_rating( null, $product_id, $meta_key, true );
696
+ } elseif ( '_product_image_gallery' === $meta_key ) {
697
+ $factory = new WCML_Product_Gallery_Filter_Factory();
698
+ $filtered_value = $factory->create()->localize_image_ids( null, $product_id, $meta_key );
699
+ } elseif ( '_thumbnail_id' === $meta_key ) {
700
+ $factory = new WCML_Product_Image_Filter_Factory();
701
+ $filtered_value = $factory->create()->localize_image_id( null, $product_id, $meta_key );
702
+ }
703
+
704
+ if ( $filtered_value ) {
705
+ $data[ $meta_key ][0] = $filtered_value;
706
+ }
707
+ }
708
+
709
+ add_filter( 'get_post_metadata', array( $this, 'filter_product_data' ), 10, 3 );
710
+ }
711
+
712
+ return $data;
713
+ }
714
+
715
+ }
inc/class-wcml-tp-support.php CHANGED
@@ -119,8 +119,11 @@ class WCML_TP_Support {
119
 
120
  $product_attributes = get_post_meta( $post_id, '_product_attributes', true );
121
 
122
- $original_post_language = $this->woocommerce_wpml->products->get_original_product_language( $post_id );
123
- $original_post_id = apply_filters( 'translate_object_id', $post_id, 'product', false, $original_post_language );
 
 
 
124
 
125
  $original_attributes = get_post_meta( $original_post_id, '_product_attributes', true );
126
 
119
 
120
  $product_attributes = get_post_meta( $post_id, '_product_attributes', true );
121
 
122
+ if( isset( $job->original_doc_id ) ){
123
+ $original_post_id = $job->original_doc_id;
124
+ }else{
125
+ $original_post_id = $this->woocommerce_wpml->products->get_original_product_id( $post_id );
126
+ }
127
 
128
  $original_attributes = get_post_meta( $original_post_id, '_product_attributes', true );
129
 
inc/class-wcml-troubleshooting.php CHANGED
@@ -2,6 +2,8 @@
2
 
3
  class WCML_Troubleshooting{
4
 
 
 
5
  private $woocommerce_wpml;
6
  private $sitepress;
7
  private $wpdb;
@@ -24,7 +26,7 @@ class WCML_Troubleshooting{
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
 
30
  function wcml_count_products_with_variations(){
@@ -148,7 +150,7 @@ class WCML_Troubleshooting{
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 );
@@ -192,7 +194,7 @@ class WCML_Troubleshooting{
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 );
@@ -305,17 +307,116 @@ class WCML_Troubleshooting{
305
  wp_send_json_success();
306
  }
307
 
308
- function get_products_needs_stock_sync(){
309
 
310
- $results = $this->wpdb->get_results("
311
  SELECT p.ID, t.trid, t.element_type
312
  FROM {$this->wpdb->posts} p
313
  JOIN {$this->wpdb->prefix}icl_translations t ON t.element_id = p.ID AND t.element_type IN ('post_product', 'post_product_variation')
314
  WHERE p.post_type in ('product', 'product_variation') AND t.source_language_code IS NULL
315
  ");
316
 
317
- return $results;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
318
  }
319
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
320
 
321
  }
2
 
3
  class WCML_Troubleshooting{
4
 
5
+ const ITEMS_PER_AJAX = 5;
6
+
7
  private $woocommerce_wpml;
8
  private $sitepress;
9
  private $wpdb;
26
  add_action('wp_ajax_trbl_duplicate_terms', array($this,'trbl_duplicate_terms'));
27
  add_action('wp_ajax_trbl_fix_product_type_terms', array($this,'trbl_fix_product_type_terms'));
28
  add_action( 'wp_ajax_trbl_sync_stock', array( $this, 'trbl_sync_stock' ) );
29
+ add_action( 'wp_ajax_fix_translated_variations_relationships', array( $this, 'fix_translated_variations_relationships' ) );
30
  }
31
 
32
  function wcml_count_products_with_variations(){
150
  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 ";
151
 
152
  if( $limit ){
153
+ $sql .= "ORDER BY p.ID LIMIT ".self::ITEMS_PER_AJAX;
154
  }
155
 
156
  $all_products = $this->wpdb->get_results( $sql );
194
  AND ( SELECT COUNT( option_id ) FROM {$this->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 ".self::ITEMS_PER_AJAX;
198
  }
199
 
200
  $all_categories = $this->wpdb->get_results( $sql );
307
  wp_send_json_success();
308
  }
309
 
310
+ function get_products_needs_stock_sync(){
311
 
312
+ $results = $this->wpdb->get_results("
313
  SELECT p.ID, t.trid, t.element_type
314
  FROM {$this->wpdb->posts} p
315
  JOIN {$this->wpdb->prefix}icl_translations t ON t.element_id = p.ID AND t.element_type IN ('post_product', 'post_product_variation')
316
  WHERE p.post_type in ('product', 'product_variation') AND t.source_language_code IS NULL
317
  ");
318
 
319
+ return $results;
320
+ }
321
+
322
+ public function fix_translated_variations_relationships(){
323
+
324
+ $nonce = array_key_exists( 'wcml_nonce', $_POST ) ? sanitize_text_field( $_POST['wcml_nonce'] ) : false;
325
+ if ( ! $nonce || ! wp_verify_nonce( $nonce, 'fix_relationships' ) ) {
326
+ wp_send_json_error( 'Invalid nonce' );
327
+ }
328
+
329
+ if ( ! current_user_can( 'manage_options' ) ) {
330
+ wp_send_json_error( 'Access error' );
331
+ }
332
+
333
+ $translated_variations = get_option( 'wcml_trbl_translated_variations' );
334
+
335
+ if( !$translated_variations ){
336
+ $translated_variations = $this->get_products_variations_needs_fix_relationships();
337
+ }
338
+
339
+ foreach ( array_slice( $translated_variations, 0, self::ITEMS_PER_AJAX, true ) as $key => $translated_variation ) {
340
+ //delete broken variations
341
+ if ( ! get_post_meta( $translated_variation->post_id, '_stock', true ) ) {
342
+ wp_delete_post( $translated_variation->post_id );
343
+ continue;
344
+ }
345
+
346
+ //check relationships
347
+ $tr_info_for_original_variation = $this->get_translation_info_for_element( $translated_variation->meta_value, 'post_product_variation' );
348
+
349
+ $language = $this->sitepress->get_language_for_element( wp_get_post_parent_id( $translated_variation->meta_value ), 'post_product' );
350
+
351
+ $language_current = $this->sitepress->get_language_for_element( wp_get_post_parent_id( $translated_variation->post_id ), 'post_product' );
352
+
353
+ $tr_info_for_current_variation = $this->get_translation_info_for_element( $translated_variation->post_id, 'post_product_variation' );
354
+
355
+ //delete wrong element_type for exists variations
356
+ if ( ! $tr_info_for_current_variation ) {
357
+ $tr_info_for_current_variation = $this->get_translation_info_for_element( $translated_variation->post_id, 'post_product' );
358
+ if ( $tr_info_for_current_variation ) {
359
+ $this->wpdb->update( $this->wpdb->prefix . 'icl_translations', array( 'element_type' => 'post_product_variation' ), array( 'translation_id' => $tr_info_for_current_variation->translation_id ) );
360
+ }
361
+ }
362
+
363
+ $check_duplicated_post_type = $this->get_translation_info_for_element( $translated_variation->post_id, 'post_product' );
364
+ if ( $check_duplicated_post_type ) {
365
+ $this->wpdb->delete( $this->wpdb->prefix . 'icl_translations', array( 'translation_id' => $check_duplicated_post_type->translation_id ) );
366
+ }
367
+
368
+
369
+ //set language info for variation if not exists
370
+ if ( ! $tr_info_for_original_variation ) {
371
+
372
+ $tr_info_for_original_variation = $this->get_translation_info_for_element( $translated_variation->meta_value, 'post_product' );
373
+ if ( $tr_info_for_original_variation ) {
374
+ $this->wpdb->update( $this->wpdb->prefix . 'icl_translations', array( 'element_type' => 'post_product_variation' ), array( 'translation_id' => $tr_info_for_original_variation->translation_id ) );
375
+ } else {
376
+ $this->sitepress->set_element_language_details( $translated_variation->meta_value, 'post_product_variation', $tr_info_for_current_variation->trid, $language );
377
+ $tr_info_for_original_variation = $this->get_translation_info_for_element( $translated_variation->meta_value, 'post_product' );
378
+ }
379
+
380
+ $this->wpdb->update( $this->wpdb->prefix . 'icl_translations', array( 'source_language_code' => $language ), array( 'translation_id' => $tr_info_for_current_variation->translation_id ) );
381
+ }
382
+
383
+ if ( $tr_info_for_original_variation->trid != $tr_info_for_current_variation->trid ) {
384
+
385
+ $this->wpdb->update( $this->wpdb->prefix . 'icl_translations', array(
386
+ 'trid' => $tr_info_for_original_variation->trid,
387
+ 'language_code' => $language_current,
388
+ 'source_language_code' => $language
389
+ ), array( 'translation_id' => $tr_info_for_current_variation->translation_id ) );
390
+
391
+ }
392
+
393
+ unset( $translated_variations[ $key ] );
394
+ }
395
+
396
+ update_option( 'wcml_trbl_translated_variations', $translated_variations );
397
+
398
+ wp_send_json_success();
399
  }
400
 
401
+ /**
402
+ * @param int $element_id
403
+ * @param string $element_type
404
+ *
405
+ * @return object|null
406
+ */
407
+ private function get_translation_info_for_element( $element_id, $element_type ){
408
+ return $this->wpdb->get_row( $this->wpdb->prepare( "SELECT trid, translation_id FROM {$this->wpdb->prefix}icl_translations WHERE element_id = %d AND element_type = %s", $element_id, $element_type ) );
409
+ }
410
+
411
+ private function get_products_variations_needs_fix_relationships(){
412
+ return $this->wpdb->get_results( "SELECT post_id, meta_value FROM {$this->wpdb->postmeta} WHERE meta_key ='_wcml_duplicate_of_variation'" );
413
+ }
414
+
415
+ public function wcml_count_product_fix_relationships(){
416
+
417
+ $results = $this->get_products_variations_needs_fix_relationships();
418
+
419
+ return count( $results );
420
+ }
421
 
422
  }
inc/class-wcml-upgrade.php CHANGED
@@ -27,7 +27,8 @@ class WCML_Upgrade{
27
  '4.3.0',
28
  '4.3.4',
29
  '4.3.5',
30
- '4.4.1'
 
31
  );
32
 
33
  function __construct(){
@@ -747,4 +748,31 @@ class WCML_Upgrade{
747
 
748
  }
749
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
750
  }
27
  '4.3.0',
28
  '4.3.4',
29
  '4.3.5',
30
+ '4.4.1',
31
+ '4.4.3',
32
  );
33
 
34
  function __construct(){
748
 
749
  }
750
 
751
+
752
+ private function upgrade_4_4_3() {
753
+ if ( class_exists( 'WC_SwatchesPlugin' ) ) {
754
+ global $wpdb, $sitepress, $wpml_post_translations;
755
+
756
+ $variation_sp = new WCML_Variation_Swatches_And_Photos( $sitepress );
757
+ $original_products = $wpdb->get_results( "
758
+ SELECT element_id
759
+ FROM {$wpdb->prefix}icl_translations
760
+ WHERE element_type = 'post_product' AND source_language_code IS NULL" );
761
+
762
+ $current_language = $sitepress->get_current_language();
763
+
764
+ foreach ( $original_products as $product ) {
765
+
766
+ $sitepress->switch_lang( $wpml_post_translations->get_element_lang_code( $product->element_id ) );
767
+
768
+ $translations = $wpml_post_translations->get_element_translations( $product->element_id, false, true );
769
+ foreach ( $translations as $translation ) {
770
+ $variation_sp->sync_variation_swatches_and_photos( $product->element_id, $translation, false );
771
+ }
772
+ }
773
+
774
+ $sitepress->switch_lang( $current_language );
775
+ }
776
+ }
777
+
778
  }
inc/currencies/class-wcml-custom-prices.php CHANGED
@@ -56,11 +56,7 @@ class WCML_Custom_Prices{
56
 
57
  if( !empty( $product_meta['_wcml_custom_prices_status'][0] ) ){
58
 
59
- $prices_keys = apply_filters( 'wcml_price_custom_fields_filtered', array(
60
- '_price', '_regular_price', '_sale_price',
61
- '_min_variation_price', '_max_variation_price',
62
- '_min_variation_regular_price', '_max_variation_regular_price',
63
- '_min_variation_sale_price', '_max_variation_sale_price' ));
64
 
65
  foreach($prices_keys as $key){
66
 
56
 
57
  if( !empty( $product_meta['_wcml_custom_prices_status'][0] ) ){
58
 
59
+ $prices_keys = wcml_price_custom_fields( $product_id );
 
 
 
 
60
 
61
  foreach($prices_keys as $key){
62
 
inc/currencies/class-wcml-multi-currency-install.php CHANGED
@@ -1,59 +1,81 @@
1
  <?php
2
 
3
- class WCML_Multi_Currency_Install{
4
-
5
- private $multi_currency;
6
- private $woocommerce_wpml;
7
-
8
- public function __construct( &$multi_currency, &$woocommerce_wpml ){
9
-
10
- $this->multi_currency =& $multi_currency;
11
- $this->woocommerce_wpml =& $woocommerce_wpml;
12
-
13
- $wcml_settings = $this->woocommerce_wpml->get_settings();
14
-
15
- if( empty( $wcml_settings['multi_currency']['set_up'] ) ){
16
- $wcml_settings['multi_currency']['set_up'] = 1;
17
- $this->woocommerce_wpml->update_settings( $wcml_settings );
18
-
19
- $this->set_default_currencies_languages();
20
- }
21
-
22
- return;
23
- }
24
-
25
- public function set_default_currencies_languages( $old_value = false, $new_value = false ){
26
- global $sitepress;
27
-
28
- $settings = $this->woocommerce_wpml->get_settings();
29
- $active_languages = $sitepress->get_active_languages();
30
- $wc_currency = $new_value ? $new_value : get_option('woocommerce_currency');
31
-
32
- if( $old_value != $new_value ) {
33
- $settings = WCML_Multi_Currency_Configuration::currency_options_update_default_currency( $settings, $old_value, $new_value );
34
- }
35
-
36
- foreach( $this->multi_currency->get_currency_codes() as $code) {
37
- if( $code == $old_value ) continue;
38
- foreach($active_languages as $language){
39
- if(!isset($settings['currency_options'][$code]['languages'][$language['code']])){
40
- $settings['currency_options'][$code]['languages'][$language['code']] = 1;
41
- }
42
- }
43
- }
44
-
45
- foreach($active_languages as $language){
46
- if(!isset($settings['default_currencies'][$language['code']])){
47
- $settings['default_currencies'][$language['code']] = false;
48
- }
49
-
50
- if(!isset($settings['currency_options'][$wc_currency]['languages'][$language['code']])){
51
- $settings['currency_options'][$wc_currency]['languages'][$language['code']] = 1;
52
- }
53
- }
54
-
55
- $this->woocommerce_wpml->update_settings( $settings );
56
-
57
- }
58
-
59
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <?php
2
 
3
+ class WCML_Multi_Currency_Install {
4
+
5
+ /**
6
+ * The \WCML_Multi_Currency instance.
7
+ *
8
+ * @var \WCML_Multi_Currency
9
+ */
10
+ private $multi_currency;
11
+ /**
12
+ * The \woocommerce_wpml instance.
13
+ *
14
+ * @var \woocommerce_wpml
15
+ */
16
+ private $woocommerce_wpml;
17
+
18
+ /**
19
+ * WCML_Multi_Currency_Install constructor.
20
+ *
21
+ * @param \WCML_Multi_Currency $multi_currency And instance of \WCML_Multi_Currency.
22
+ * @param \woocommerce_wpml $woocommerce_wpml And instance of \woocommerce_wpml.
23
+ */
24
+ public function __construct( WCML_Multi_Currency $multi_currency, woocommerce_wpml $woocommerce_wpml ) {
25
+
26
+ $this->multi_currency = $multi_currency;
27
+ $this->woocommerce_wpml = $woocommerce_wpml;
28
+
29
+ $wcml_settings = $this->woocommerce_wpml->get_settings();
30
+
31
+ if ( empty( $wcml_settings['multi_currency']['set_up'] ) ) {
32
+ $wcml_settings['multi_currency']['set_up'] = 1;
33
+ $this->woocommerce_wpml->update_settings( $wcml_settings );
34
+
35
+ $this->set_default_currencies_languages();
36
+ }
37
+ }
38
+
39
+ /**
40
+ * It sets the default currency for each language.
41
+ *
42
+ * @param bool|string $old_value The value of the option before the update.
43
+ * @param bool|string $new_value The new value of the option.
44
+ */
45
+ public function set_default_currencies_languages( $old_value = false, $new_value = false ) {
46
+ global $sitepress;
47
+
48
+ $settings = $this->woocommerce_wpml->get_settings();
49
+ $active_languages = $sitepress->get_active_languages();
50
+ $wc_currency = $new_value ? $new_value : get_option( 'woocommerce_currency' );
51
+
52
+ if ( $old_value !== $new_value ) {
53
+ $settings = WCML_Multi_Currency_Configuration::currency_options_update_default_currency( $settings, $old_value, $new_value );
54
+ }
55
+
56
+ foreach ( $this->multi_currency->get_currency_codes() as $code ) {
57
+ if ( $code === $old_value ) {
58
+ continue;
59
+ }
60
+ foreach ( $active_languages as $language ) {
61
+ if ( ! isset( $settings['currency_options'][ $code ]['languages'][ $language['code'] ] ) ) {
62
+ $settings['currency_options'][ $code ]['languages'][ $language['code'] ] = 1;
63
+ }
64
+ }
65
+ }
66
+
67
+ foreach ( $active_languages as $language ) {
68
+ if ( ! isset( $settings['default_currencies'][ $language['code'] ] ) ) {
69
+ $settings['default_currencies'][ $language['code'] ] = false;
70
+ }
71
+
72
+ if ( ! isset( $settings['currency_options'][ $wc_currency ]['languages'][ $language['code'] ] ) ) {
73
+ $settings['currency_options'][ $wc_currency ]['languages'][ $language['code'] ] = 1;
74
+ }
75
+ }
76
+
77
+ $this->woocommerce_wpml->update_settings( $settings );
78
+
79
+ }
80
+
81
+ }
inc/currencies/class-wcml-multi-currency-orders.php CHANGED
@@ -66,10 +66,11 @@ class WCML_Multi_Currency_Orders {
66
  $currencies = array();
67
 
68
  $results = $wpdb->get_results( "
69
- SELECT m.meta_value AS currency, COUNT(m.post_id) AS c
70
- FROM {$wpdb->posts} p JOIN {$wpdb->postmeta} m ON p.ID = m.post_id
71
- WHERE meta_key='_order_currency' AND p.post_type='shop_order'
72
- GROUP BY meta_value
 
73
  " );
74
 
75
  foreach ( $results as $row ) {
@@ -79,7 +80,6 @@ class WCML_Multi_Currency_Orders {
79
  wp_cache_set( $cache_key, $currencies );
80
 
81
  return $currencies;
82
-
83
  }
84
 
85
  public function show_orders_currencies_selector() {
@@ -256,8 +256,7 @@ class WCML_Multi_Currency_Orders {
256
 
257
  public function set_totals_for_order_items( $items ) {
258
 
259
- if ( isset( $_POST['action'] ) && 'woocommerce_add_order_item' === $_POST['action'] ) {
260
-
261
  foreach ( $items as $item ) {
262
  $this->set_converted_totals_for_item( $item );
263
  }
@@ -270,6 +269,7 @@ class WCML_Multi_Currency_Orders {
270
 
271
  $itemmeta[] = '_wcml_converted_subtotal';
272
  $itemmeta[] = '_wcml_converted_total';
 
273
 
274
  return $itemmeta;
275
  }
@@ -280,6 +280,10 @@ class WCML_Multi_Currency_Orders {
280
 
281
  if ( ! $order_currency ) {
282
  $order_currency = $this->get_order_currency_cookie();
 
 
 
 
283
  }
284
 
285
  if ( ! isset( $this->multi_currency->prices ) ) {
@@ -296,31 +300,44 @@ class WCML_Multi_Currency_Orders {
296
  $original_product_id = $this->woocommerce_wpml->products->get_original_product_id( $product_id );
297
 
298
  $converted_price = get_post_meta( $original_product_id, '_price_' . $order_currency, true );
 
299
 
300
  if ( ! $converted_price ) {
301
- if( $item->meta_exists( '_wcml_converted_subtotal' ) ){
302
- $converted_subtotal_price = $item->get_meta( '_wcml_converted_subtotal' ) * $item->get_quantity();
303
- }else{
304
- $converted_subtotal_price = $this->multi_currency->prices->raw_price_filter( $item->get_subtotal(), $order_currency );
305
- $item->add_meta_data('_wcml_converted_subtotal', $converted_subtotal_price );
 
 
 
 
306
  }
307
 
308
- if( $item->meta_exists( '_wcml_converted_total' ) ){
309
- $converted_total_price = $item->get_meta( '_wcml_converted_total' ) * $item->get_quantity();
310
- }else{
311
- $converted_total_price = $this->multi_currency->prices->raw_price_filter( $item->get_total(), $order_currency );
312
- $item->add_meta_data('_wcml_converted_total', $converted_total_price );
 
 
 
 
313
  }
 
 
314
  }else{
315
 
316
  $converted_price = wc_get_price_excluding_tax( $item->get_product(), array( 'price' => $converted_price, 'qty' => $item->get_quantity() ) );
317
-
318
- $converted_subtotal_price = $converted_price;
319
- $converted_total_price = $converted_price;
320
  }
321
 
322
- $item->set_subtotal( $converted_subtotal_price );
323
- $item->set_total( $converted_total_price );
 
 
324
  $item->save();
325
  }
326
  } else {
66
  $currencies = array();
67
 
68
  $results = $wpdb->get_results( "
69
+ SELECT LEFT(m.meta_value, 3) AS currency, COUNT(*) AS c
70
+ FROM {$wpdb->postmeta} m
71
+ INNER JOIN {$wpdb->posts} p on p.ID = m.post_id
72
+ WHERE m.meta_key='_order_currency' AND p.post_type='shop_order'
73
+ GROUP BY currency
74
  " );
75
 
76
  foreach ( $results as $row ) {
80
  wp_cache_set( $cache_key, $currencies );
81
 
82
  return $currencies;
 
83
  }
84
 
85
  public function show_orders_currencies_selector() {
256
 
257
  public function set_totals_for_order_items( $items ) {
258
 
259
+ if ( isset( $_POST['action'] ) && in_array( $_POST['action'], array( 'woocommerce_add_order_item', 'woocommerce_save_order_items' ), true ) ) {
 
260
  foreach ( $items as $item ) {
261
  $this->set_converted_totals_for_item( $item );
262
  }
269
 
270
  $itemmeta[] = '_wcml_converted_subtotal';
271
  $itemmeta[] = '_wcml_converted_total';
272
+ $itemmeta[] = '_wcml_total_qty';
273
 
274
  return $itemmeta;
275
  }
280
 
281
  if ( ! $order_currency ) {
282
  $order_currency = $this->get_order_currency_cookie();
283
+
284
+ if ( in_array( $_POST['action'], array( 'woocommerce_add_order_item', 'woocommerce_save_order_items' ), true ) ) {
285
+ update_post_meta( $_POST['order_id'], '_order_currency', $order_currency );
286
+ }
287
  }
288
 
289
  if ( ! isset( $this->multi_currency->prices ) ) {
300
  $original_product_id = $this->woocommerce_wpml->products->get_original_product_id( $product_id );
301
 
302
  $converted_price = get_post_meta( $original_product_id, '_price_' . $order_currency, true );
303
+ $converted_totals = array( 'subtotal' => 0, 'total' => 0 );
304
 
305
  if ( ! $converted_price ) {
306
+
307
+ foreach( array_keys( $converted_totals ) as $key ) {
308
+ $meta_key = '_wcml_converted_' . $key;
309
+ if ( $item->meta_exists( $meta_key ) ) {
310
+ $converted_totals[ $key ] = $item->get_meta( $meta_key );
311
+ } else {
312
+ $converted_totals[ $key ] = $this->multi_currency->prices->raw_price_filter( call_user_func_array( array( $item, 'get_' . $key ), array() ), $order_currency );
313
+ $item->add_meta_data( $meta_key, $converted_totals[ $key ] );
314
+ }
315
  }
316
 
317
+ //re-calculate only new added items for performance reason
318
+ if ( $item->meta_exists( '_wcml_total_qty' ) && $item->get_quantity() !== (int)$item->get_meta( '_wcml_total_qty' ) ) {
319
+
320
+ $new_total = $item->get_quantity() * $this->multi_currency->prices->raw_price_filter( $item->get_product()->get_price(), $order_currency );
321
+
322
+ foreach( array_keys( $converted_totals ) as $key ) {
323
+ $converted_totals[ $key ] = $new_total;
324
+ $item->update_meta_data( '_wcml_converted_' . $key, $new_total );
325
+ }
326
  }
327
+
328
+ $item->update_meta_data( '_wcml_total_qty', $item->get_quantity() );
329
  }else{
330
 
331
  $converted_price = wc_get_price_excluding_tax( $item->get_product(), array( 'price' => $converted_price, 'qty' => $item->get_quantity() ) );
332
+ foreach( array_keys( $converted_totals ) as $key ) {
333
+ $converted_totals[ $key ] = $converted_price;
334
+ }
335
  }
336
 
337
+ foreach( array_keys( $converted_totals ) as $key ) {
338
+ call_user_func_array( array( $item, 'set_' . $key ), array( $converted_totals[ $key ] ) );
339
+ }
340
+
341
  $item->save();
342
  }
343
  } else {
inc/currencies/class-wcml-multi-currency-prices.php CHANGED
@@ -158,19 +158,9 @@ class WCML_Multi_Currency_Prices {
158
 
159
  if ( empty( $no_filter ) && in_array( get_post_type( $object_id ), array( 'product', 'product_variation' ) ) ) {
160
 
161
- $price_keys = apply_filters( 'wcml_price_custom_fields_filtered', array(
162
- '_price',
163
- '_regular_price',
164
- '_sale_price',
165
- '_min_variation_price',
166
- '_max_variation_price',
167
- '_min_variation_regular_price',
168
- '_max_variation_regular_price',
169
- '_min_variation_sale_price',
170
- '_max_variation_sale_price'
171
- ) );
172
 
173
- if ( in_array( $meta_key, $price_keys ) ) {
174
  $no_filter = true;
175
 
176
  // exception for products migrated from before WCML 3.1 with independent prices
@@ -799,4 +789,4 @@ class WCML_Multi_Currency_Prices {
799
  return get_post_meta( $product->get_id(), '_price', 1 );
800
  }
801
 
802
- }
158
 
159
  if ( empty( $no_filter ) && in_array( get_post_type( $object_id ), array( 'product', 'product_variation' ) ) ) {
160
 
161
+ $price_keys = wcml_price_custom_fields( $object_id );
 
 
 
 
 
 
 
 
 
 
162
 
163
+ if ( is_array( $price_keys ) && in_array( $meta_key, $price_keys ) ) {
164
  $no_filter = true;
165
 
166
  // exception for products migrated from before WCML 3.1 with independent prices
789
  return get_post_meta( $product->get_id(), '_price', 1 );
790
  }
791
 
792
+ }
inc/currencies/class-wcml-multi-currency.php CHANGED
@@ -498,12 +498,14 @@ class WCML_Multi_Currency{
498
  }
499
  }
500
 
 
 
501
  if(!empty($woocommerce->session) && $this->client_currency){
502
  $woocommerce->session->set('client_currency', $this->client_currency);
503
  $woocommerce->session->set('client_currency_language',$current_language);
504
  }
505
 
506
- return apply_filters('wcml_client_currency', $this->client_currency);
507
  }
508
 
509
  public function maybe_show_switching_currency_prompt_dialog(){
498
  }
499
  }
500
 
501
+ $this->client_currency = apply_filters( 'wcml_client_currency', $this->client_currency );
502
+
503
  if(!empty($woocommerce->session) && $this->client_currency){
504
  $woocommerce->session->set('client_currency', $this->client_currency);
505
  $woocommerce->session->set('client_currency_language',$current_language);
506
  }
507
 
508
+ return $this->client_currency;
509
  }
510
 
511
  public function maybe_show_switching_currency_prompt_dialog(){
inc/missing-php-functions.php CHANGED
@@ -50,6 +50,12 @@ function wcml_check_wpml_functions() {
50
  }
51
  }
52
 
 
 
 
 
 
 
53
  }
54
 
55
  // two WordPress functions that were added in 4.4.0
50
  }
51
  }
52
 
53
+ if( !function_exists( 'wpml_is_rest_request' ) && defined( 'ICL_SITEPRESS_VERSION' ) && version_compare( ICL_SITEPRESS_VERSION, '4.2.0', '<' ) ){
54
+ function wpml_is_rest_request() {
55
+ return array_key_exists( 'rest_route', $_REQUEST ) || false !== strpos( $_SERVER['REQUEST_URI'], 'wp-json' );
56
+ }
57
+ }
58
+
59
  }
60
 
61
  // two WordPress functions that were added in 4.4.0
inc/template-classes/class-wcml-troubleshooting-ui.php CHANGED
@@ -27,6 +27,7 @@ class WCML_Troubleshooting_UI extends WPML_Templates_Factory {
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'),
@@ -45,6 +46,7 @@ class WCML_Troubleshooting_UI extends WPML_Templates_Factory {
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(
@@ -55,6 +57,7 @@ class WCML_Troubleshooting_UI extends WPML_Templates_Factory {
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
 
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
+ 'fix_relationships_count' => $this->woocommerce_wpml->troubleshooting->wcml_count_product_fix_relationships(),
31
  'all_products_taxonomies' => $this->get_all_products_taxonomies(),
32
  'product_type_sync_needed' => !empty( $translated_product_type_terms ) ? true : false,
33
  'media_def' => defined('WPML_MEDIA_VERSION'),
46
  'start' => __( 'Start', 'woocommerce-multilingual' ),
47
  'delete_terms' => __( 'Fix product_type taxonomy terms', 'woocommerce-multilingual' ),
48
  'sync_stock' => __( 'Sync product stock quantity and status ( synchronizing min stock between translations )', 'woocommerce-multilingual' ),
49
+ 'sync_relationships' => __( 'Fix translated variations relationships', 'woocommerce-multilingual' ),
50
  'product_type_fix_done' => __( 'Done!', 'woocommerce-multilingual' )
51
  ),
52
  'nonces' => array(
57
  'trbl_duplicate_terms' => wp_nonce_field('trbl_duplicate_terms', 'trbl_duplicate_terms_nonce'),
58
  'trbl_product_type_terms' => wp_nonce_field('trbl_product_type_terms', 'trbl_product_type_terms_nonce'),
59
  'trbl_sync_stock' => wp_nonce_field('trbl_sync_stock', 'trbl_sync_stock_nonce'),
60
+ 'fix_relationships' => wp_nonce_field( 'fix_relationships', 'fix_relationships_nonce' ),
61
  )
62
  );
63
 
inc/template-classes/multi-currency/class-wcml-exchange-rates-ui.php CHANGED
@@ -26,7 +26,6 @@ class WCML_Exchange_Rates_UI extends WPML_Templates_Factory {
26
  $this->services[ $id ] = array(
27
  'name' => $service->get_name(),
28
  'url' => $service->get_url(),
29
- 'requires_key' => $service->is_key_required(),
30
  'api_key' => $service->get_setting( 'api-key' ),
31
  'last_error' => $service->get_last_error()
32
  );
26
  $this->services[ $id ] = array(
27
  'name' => $service->get_name(),
28
  'url' => $service->get_url(),
 
29
  'api_key' => $service->get_setting( 'api-key' ),
30
  'last_error' => $service->get_last_error()
31
  );
inc/translation-editor/class-wcml-editor-ui-product-job.php CHANGED
@@ -724,6 +724,8 @@ class WCML_Editor_UI_Product_Job extends WPML_Editor_UI_Job {
724
 
725
  $this->woocommerce_wpml->sync_product_data->sync_linked_products( $this->product_id, $tr_product_id, $this->get_target_language() );
726
 
 
 
727
  //sync feature image
728
  $this->woocommerce_wpml->media->sync_thumbnail_id( $this->product_id, $tr_product_id, $this->get_target_language() );
729
  //sync product gallery
724
 
725
  $this->woocommerce_wpml->sync_product_data->sync_linked_products( $this->product_id, $tr_product_id, $this->get_target_language() );
726
 
727
+ $this->woocommerce_wpml->sync_product_data->sync_product_stock( $this->product, wc_get_product( $tr_product_id ) );
728
+
729
  //sync feature image
730
  $this->woocommerce_wpml->media->sync_thumbnail_id( $this->product_id, $tr_product_id, $this->get_target_language() );
731
  //sync product gallery
inc/translation-editor/class-wcml-page-builders.php CHANGED
@@ -56,9 +56,11 @@ class WCML_Page_Builders {
56
  foreach ( $string_packages as $string_package ) {
57
  $strings_section = new WPML_Editor_UI_Field_Section( $string_package['title'] );
58
 
59
- foreach ( $string_package['strings'] as $string ) {
60
- $field_label = apply_filters( 'wpml_string_title_from_id', false, $string->id );
61
- $strings_section->add_field( new WCML_Editor_UI_WYSIWYG_Field( $string->name, $field_label, $data, true ) );
 
 
62
  }
63
  }
64
 
@@ -71,10 +73,12 @@ class WCML_Page_Builders {
71
 
72
  foreach ( $string_packages as $string_package ) {
73
 
74
- foreach ( $string_package['strings'] as $string ) {
75
- $element_data[ $string->name ] = array( 'original' => $string->value );
76
- if ( isset( $string->translated_value ) ) {
77
- $element_data[ $string->name ]['translation'] = $string->translated_value;
 
 
78
  }
79
  }
80
  }
@@ -88,16 +92,18 @@ class WCML_Page_Builders {
88
 
89
  foreach ( $string_packages as $string_package ) {
90
 
91
- foreach ( $string_package['strings'] as $string ) {
 
92
 
93
- do_action(
94
- 'wpml_add_string_translation',
95
- $string->id,
96
- $target_language,
97
- $translations[ md5( $string->name ) ],
98
- $this->sitepress->get_wp_api()->constant( 'ICL_TM_COMPLETE' )
99
- );
100
 
 
101
  }
102
  }
103
  }
56
  foreach ( $string_packages as $string_package ) {
57
  $strings_section = new WPML_Editor_UI_Field_Section( $string_package['title'] );
58
 
59
+ if( isset( $string_package['strings'] ) ) {
60
+ foreach ( $string_package['strings'] as $string ) {
61
+ $field_label = apply_filters( 'wpml_string_title_from_id', false, $string->id );
62
+ $strings_section->add_field( new WCML_Editor_UI_WYSIWYG_Field( $string->name, $field_label, $data, true ) );
63
+ }
64
  }
65
  }
66
 
73
 
74
  foreach ( $string_packages as $string_package ) {
75
 
76
+ if( isset( $string_package['strings'] ) ){
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
  }
92
 
93
  foreach ( $string_packages as $string_package ) {
94
 
95
+ if( isset( $string_package['strings'] ) ) {
96
+ foreach ( $string_package['strings'] as $string ) {
97
 
98
+ do_action(
99
+ 'wpml_add_string_translation',
100
+ $string->id,
101
+ $target_language,
102
+ $translations[ md5( $string->name ) ],
103
+ $this->sitepress->get_wp_api()->constant( 'ICL_TM_COMPLETE' )
104
+ );
105
 
106
+ }
107
  }
108
  }
109
  }
inc/translation-editor/class-wcml-synchronize-product-data.php CHANGED
@@ -32,11 +32,13 @@ class WCML_Synchronize_Product_Data{
32
  }
33
 
34
  public function add_hooks(){
35
- if( is_admin() ){
36
- // filters to sync variable products
37
- add_action( 'save_post', array( $this, 'synchronize_products' ), PHP_INT_MAX, 2 ); // After WPML
38
 
39
- add_action( 'icl_pro_translation_completed', array( $this, 'icl_pro_translation_completed' ) );
 
 
40
 
41
  add_filter( 'icl_make_duplicate', array( $this, 'icl_make_duplicate'), 110, 4 );
42
 
@@ -78,7 +80,7 @@ class WCML_Synchronize_Product_Data{
78
  $var_lang = $this->sitepress->get_language_for_element( wp_get_post_parent_id( $post_id ), 'post_product' );
79
  $is_parent_original = $this->woocommerce_wpml->products->is_original_product( wp_get_post_parent_id( $post_id ) );
80
  $variation_language_details = $this->sitepress->get_element_language_details( $post_id, 'post_product_variation' );
81
- if( $is_parent_original && !$variation_language_details ){
82
  $this->sitepress->set_element_language_details( $post_id, 'post_product_variation', false, $var_lang );
83
  }
84
  }
@@ -167,6 +169,8 @@ class WCML_Synchronize_Product_Data{
167
 
168
  $this->sync_linked_products( $original_product_id, $tr_product_id, $lang );
169
 
 
 
170
  // Clear any unwanted data
171
  wc_delete_product_transients( $tr_product_id );
172
  }
@@ -308,20 +312,25 @@ class WCML_Synchronize_Product_Data{
308
 
309
  /**
310
  * @param $product
 
311
  */
312
- public function sync_product_stock( $product ) {
 
313
  $stock = $product->get_stock_quantity();
314
  $product_id = $product->get_id();
315
 
316
  remove_action( 'woocommerce_product_set_stock', array( $this, 'sync_product_stock' ) );
317
  remove_action( 'woocommerce_variation_set_stock', array( $this, 'sync_product_stock' ) );
318
 
319
- $translations = $this->post_translations->get_element_translations( $product_id );
320
-
321
- foreach( $translations as $translation ){
322
- if( $product_id !== $translation ){
323
- $_product = wc_get_product( $translation );
324
- wc_update_product_stock( $_product, $stock );
 
 
 
325
  }
326
  }
327
 
32
  }
33
 
34
  public function add_hooks(){
35
+ if( is_admin() || wpml_is_rest_request() ) {
36
+ add_action( 'icl_pro_translation_completed', array( $this, 'icl_pro_translation_completed' ) );
37
+ }
38
 
39
+ if( is_admin() ){
40
+ // filters to sync variable products
41
+ add_action( 'save_post', array( $this, 'synchronize_products' ), PHP_INT_MAX, 2 ); // After WPML
42
 
43
  add_filter( 'icl_make_duplicate', array( $this, 'icl_make_duplicate'), 110, 4 );
44
 
80
  $var_lang = $this->sitepress->get_language_for_element( wp_get_post_parent_id( $post_id ), 'post_product' );
81
  $is_parent_original = $this->woocommerce_wpml->products->is_original_product( wp_get_post_parent_id( $post_id ) );
82
  $variation_language_details = $this->sitepress->get_element_language_details( $post_id, 'post_product_variation' );
83
+ if( $is_parent_original && !$variation_language_details && $var_lang ){
84
  $this->sitepress->set_element_language_details( $post_id, 'post_product_variation', false, $var_lang );
85
  }
86
  }
169
 
170
  $this->sync_linked_products( $original_product_id, $tr_product_id, $lang );
171
 
172
+ $this->sync_product_stock( wc_get_product( $original_product_id ), wc_get_product( $tr_product_id ) );
173
+
174
  // Clear any unwanted data
175
  wc_delete_product_transients( $tr_product_id );
176
  }
312
 
313
  /**
314
  * @param $product
315
+ * @param $translated_product
316
  */
317
+ public function sync_product_stock( $product, $translated_product = false ) {
318
+
319
  $stock = $product->get_stock_quantity();
320
  $product_id = $product->get_id();
321
 
322
  remove_action( 'woocommerce_product_set_stock', array( $this, 'sync_product_stock' ) );
323
  remove_action( 'woocommerce_variation_set_stock', array( $this, 'sync_product_stock' ) );
324
 
325
+ if( $translated_product ){
326
+ wc_update_product_stock( $translated_product, $stock );
327
+ }else{
328
+ $translations = $this->post_translations->get_element_translations( $product_id );
329
+ foreach( $translations as $translation ){
330
+ if( $product_id !== $translation ){
331
+ $_product = wc_get_product( $translation );
332
+ wc_update_product_stock( $_product, $stock );
333
+ }
334
  }
335
  }
336
 
inc/translation-editor/class-wcml-synchronize-variations-data.php CHANGED
@@ -170,6 +170,8 @@ class WCML_Synchronize_Variations_Data{
170
 
171
  $this->delete_removed_variation_attributes( $product_id, $variation_id );
172
 
 
 
173
  //refresh parent-children transients
174
  delete_transient( 'wc_product_children_' . $tr_product_id );
175
  delete_transient( '_transient_wc_product_children_ids_' . $tr_product_id );
170
 
171
  $this->delete_removed_variation_attributes( $product_id, $variation_id );
172
 
173
+ $this->woocommerce_wpml->sync_product_data->sync_product_stock( wc_get_product( $original_variation_id ), wc_get_product( $variation_id ) );
174
+
175
  //refresh parent-children transients
176
  delete_transient( 'wc_product_children_' . $tr_product_id );
177
  delete_transient( '_transient_wc_product_children_ids_' . $tr_product_id );
inc/translation-editor/class-wcml-translation-editor.php CHANGED
@@ -28,25 +28,21 @@ class WCML_Translation_Editor{
28
  add_filter( 'manage_product_posts_columns', array( $this, 'add_languages_column' ), 100 );
29
  add_action( 'woocommerce_product_after_variable_attributes', array( $this, 'lock_variable_fields' ), 10 );
30
 
31
- if( is_admin() ){
32
-
33
- add_filter( 'wpml_use_tm_editor', array( $this, 'force_woocommerce_native_editor_for_wcml_products_screen' ), 100 );
34
-
35
- if( $this->woocommerce_wpml->is_wpml_prior_4_2() ) {
36
- add_filter( 'wpml_use_tm_editor', array( $this, 'force_woocommerce_native_editor' ), 100 );
37
- add_action( 'wpml_pre_status_icon_display', array(
38
- $this,
39
- 'force_remove_wpml_translation_editor_links'
40
- ), 100 );
41
- }
42
-
43
- add_action( 'wp_ajax_wcml_editor_auto_slug', array( $this, 'auto_generate_slug' ) );
44
 
45
- add_action('wpml_doc_translation_method_below', array( $this, 'wpml_translation_editor_override_notice') );
46
 
47
- add_filter( 'wpml_tm_show_page_builders_translation_editor_warning', array( $this, 'show_page_builders_translation_editor_warning' ), 10, 2 );
48
- }
49
 
 
50
  }
51
 
52
  public function fetch_translation_job_for_editor( $job, $job_details ) {
@@ -287,7 +283,7 @@ class WCML_Translation_Editor{
287
 
288
  if( function_exists('get_current_screen') ) {
289
  $current_screen = get_current_screen();
290
- if ( $current_screen->id === 'woocommerce_page_wpml-wcml' ) {
291
  $use_tm_editor = 1;
292
  }
293
  }
28
  add_filter( 'manage_product_posts_columns', array( $this, 'add_languages_column' ), 100 );
29
  add_action( 'woocommerce_product_after_variable_attributes', array( $this, 'lock_variable_fields' ), 10 );
30
 
31
+ add_filter( 'wpml_use_tm_editor', array( $this, 'force_woocommerce_native_editor_for_wcml_products_screen' ), 100 );
32
+
33
+ if( $this->woocommerce_wpml->is_wpml_prior_4_2() ) {
34
+ add_filter( 'wpml_use_tm_editor', array( $this, 'force_woocommerce_native_editor' ), 100 );
35
+ add_action( 'wpml_pre_status_icon_display', array(
36
+ $this,
37
+ 'force_remove_wpml_translation_editor_links'
38
+ ), 100 );
39
+ }
 
 
 
 
40
 
41
+ add_action( 'wp_ajax_wcml_editor_auto_slug', array( $this, 'auto_generate_slug' ) );
42
 
43
+ add_action('wpml_doc_translation_method_below', array( $this, 'wpml_translation_editor_override_notice') );
 
44
 
45
+ add_filter( 'wpml_tm_show_page_builders_translation_editor_warning', array( $this, 'show_page_builders_translation_editor_warning' ), 10, 2 );
46
  }
47
 
48
  public function fetch_translation_job_for_editor( $job, $job_details ) {
283
 
284
  if( function_exists('get_current_screen') ) {
285
  $current_screen = get_current_screen();
286
+ if ( $current_screen && $current_screen->id === 'woocommerce_page_wpml-wcml' ) {
287
  $use_tm_editor = 1;
288
  }
289
  }
inc/wcml-core-functions.php CHANGED
@@ -1,16 +1,67 @@
1
  <?php
2
 
3
- /**
4
- * @return bool
5
- *
6
- * @since 3.8.3
7
- */
8
- function wcml_is_multi_currency_on(){
9
- global $woocommerce_wpml;
10
-
11
- if( is_null( $woocommerce_wpml ) ){
12
- return false;
13
- }
14
-
15
- return $woocommerce_wpml->settings['enable_multi_currency'] == WCML_MULTI_CURRENCIES_INDEPENDENT;
16
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <?php
2
 
3
+ if ( ! function_exists( 'wcml_is_multi_currency_on' ) ) {
4
+ /**
5
+ * It returns true if multi currency is enabled.
6
+ *
7
+ * @return bool
8
+ *
9
+ * @since 3.8.3
10
+ */
11
+ function wcml_is_multi_currency_on() {
12
+ global $woocommerce_wpml;
13
+
14
+ if ( is_null( $woocommerce_wpml ) ) {
15
+ return false;
16
+ }
17
+
18
+ return WCML_MULTI_CURRENCIES_INDEPENDENT === (int) $woocommerce_wpml->settings['enable_multi_currency'];
19
+ }
20
+ }
21
+
22
+ if ( ! function_exists( 'wcml_price_custom_fields' ) ) {
23
+ /**
24
+ * It returns a filtered array of price custom fields.
25
+ *
26
+ * @param int|\WP_Post $object_id The post, product ID or object extending "WP_Post".
27
+ *
28
+ * @return array
29
+ */
30
+ function wcml_price_custom_fields( $object_id ) {
31
+ $default_keys = array(
32
+ '_max_variation_price',
33
+ '_max_variation_regular_price',
34
+ '_max_variation_sale_price',
35
+ '_min_variation_price',
36
+ '_min_variation_regular_price',
37
+ '_min_variation_sale_price',
38
+ '_price',
39
+ '_regular_price',
40
+ '_sale_price',
41
+ );
42
+
43
+ /**
44
+ * See the following filter.
45
+ *
46
+ * @deprecated
47
+ * @see apply_filters( 'wcml_price_custom_fields', $filtered_keys, $object_id );
48
+ */
49
+ $filtered_keys = apply_filters( 'wcml_price_custom_fields_filtered', $default_keys, $object_id );
50
+
51
+ /**
52
+ * It filters the array of price custom fields.
53
+ *
54
+ * If the returned filter is not an array, it will be replaced with the original value.
55
+ *
56
+ * @param array $default_keys Default unfiltered values.
57
+ * @param int|WP_Post $object_id The post, product ID or object extending "WP_Post".
58
+ */
59
+ $filtered_keys = apply_filters( 'wcml_price_custom_fields', $filtered_keys, $object_id );
60
+
61
+ if ( ! is_array( $filtered_keys ) ) {
62
+ $filtered_keys = $default_keys;
63
+ }
64
+
65
+ return $filtered_keys;
66
+ }
67
+ }
readme.txt CHANGED
@@ -4,8 +4,8 @@ Donate link: http://wpml.org/documentation/related-projects/woocommerce-multilin
4
  Tags: CMS, woocommerce, commerce, ecommerce, e-commerce, products, WPML, multilingual, e-shop, shop
5
  License: GPLv2
6
  Requires at least: 3.9
7
- Tested up to: 5.1
8
- Stable tag: 4.4.2.1
9
 
10
  Allows running fully multilingual e-commerce sites using WooCommerce and WPML.
11
 
@@ -140,6 +140,29 @@ WooCommerce Multilingual is compatible with all major WooCommerce extensions. We
140
 
141
  == Changelog ==
142
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
  = 4.4.2.1 =
144
  * Fix error while updating product
145
 
@@ -162,7 +185,6 @@ WooCommerce Multilingual is compatible with all major WooCommerce extensions. We
162
  * Fix and removed duplicated entries in code
163
  * Hide reviews in other languages link, if there are no reviews in product
164
  * Update WCML Logo
165
- * Added support for wpml endpoints
166
  * Removed Product Type Column from WCML backend and added compatibility with the WC Product Type Column plugin
167
  * Fix low_stock_amount not synchronized to translations
168
  * Fix custom attribute with number in name not appears to translation in Translation editor
@@ -196,6 +218,7 @@ WooCommerce Multilingual is compatible with all major WooCommerce extensions. We
196
  * Fixed missed synchronization of 'outofstock' visibility term between product translations
197
  * Fix broken logic with Table Rate Shipping when product uses class with "break and abort" rule
198
  * Custom attributes terms not copied to diplicated translation after update values in original
 
199
  * WP Fastest Cache compatibility - fixed currency switcher problem
200
  * Added ability to set custom prices for secondary currencies in WC Product Add-Ons
201
  * Update minimum requirements
@@ -494,6 +517,9 @@ WooCommerce Multilingual is compatible with all major WooCommerce extensions. We
494
  * Fixed "Invalid or duplicated SKU" error when saving or updating a product with SKU
495
  * Fixed `Fatal error: Call to undefined function WC()` when disabling WooCommerce while WCML is running
496
 
 
 
 
497
  = 4.1.0 =
498
  * Enhanced language switchers
499
  * Improved REST API support
4
  Tags: CMS, woocommerce, commerce, ecommerce, e-commerce, products, WPML, multilingual, e-shop, shop
5
  License: GPLv2
6
  Requires at least: 3.9
7
+ Tested up to: 5.1.1
8
+ Stable tag: 4.5.0
9
 
10
  Allows running fully multilingual e-commerce sites using WooCommerce and WPML.
11
 
140
 
141
  == Changelog ==
142
 
143
+ = 4.5.0 =
144
+ * Add "get_post_metadata" hook to filter Woocommerce product data
145
+ * Added function in troubleshooting page to fix broken variations
146
+ * Fix refreshing of status icon when ATE Job of updated content is synced
147
+ * Fix few notices when removing a Elementor widget and refresh page
148
+ * Fetch ATE translations from WCML Product Translation Tab
149
+ * Fix warning when adding comment to product
150
+ * Fixed wrong price calculation when adding product to new order on backend
151
+ * Fixed bookings counter on admin bookings listing page
152
+ * Fixed stock quantity not synchronized to translation when creating it
153
+ * Fixed notice when saving translation
154
+ * Fixed translated attributes via ATE/Translation service not connected to translated product
155
+ * Fix not translated "On Hold" email subject after returning order from "Processing"
156
+ * Remove unneded $_SESSION variables on checkout page
157
+ * Fix PHP notice `Notice: Only variables should be passed by reference`
158
+ * Implemented dependency check for minimum compatible versions of required WPML plugins
159
+ * Fixed default variation not pre-selected on front-end for translated product with non latin attribute in default language
160
+ * Fix cannot change currency with "wcml_client_currency" filter
161
+ * Fixed not valid API key when trying manually update exchange rates
162
+ * WooCommerce Variation Swatches and Photos compatibility to translate attributes
163
+ * Fix related product displays in all languages
164
+ * Added compatibility with Yikes Custom Product Tabs
165
+
166
  = 4.4.2.1 =
167
  * Fix error while updating product
168
 
185
  * Fix and removed duplicated entries in code
186
  * Hide reviews in other languages link, if there are no reviews in product
187
  * Update WCML Logo
 
188
  * Removed Product Type Column from WCML backend and added compatibility with the WC Product Type Column plugin
189
  * Fix low_stock_amount not synchronized to translations
190
  * Fix custom attribute with number in name not appears to translation in Translation editor
218
  * Fixed missed synchronization of 'outofstock' visibility term between product translations
219
  * Fix broken logic with Table Rate Shipping when product uses class with "break and abort" rule
220
  * Custom attributes terms not copied to diplicated translation after update values in original
221
+ * Added support for wpml endpoints
222
  * WP Fastest Cache compatibility - fixed currency switcher problem
223
  * Added ability to set custom prices for secondary currencies in WC Product Add-Ons
224
  * Update minimum requirements
517
  * Fixed "Invalid or duplicated SKU" error when saving or updating a product with SKU
518
  * Fixed `Fatal error: Call to undefined function WC()` when disabling WooCommerce while WCML is running
519
 
520
+ = 4.1.0 =
521
+ * Fixed bookings issues
522
+
523
  = 4.1.0 =
524
  * Enhanced language switchers
525
  * Improved REST API support
res/css/management.css CHANGED
@@ -1 +1 @@
1
- .wcml-wrap{border:1px solid #CCCCCC;padding:15px;background-color:#ffffff}.wcml-wrap:before,.wcml-wrap:after{content:" ";display:table}.wcml-wrap:after{clear:both}.dis_base{opacity:0.5}.display-block{display:block}.wcml-wrap{margin-bottom:20px}.wcml-wrap .wpml-tabs{margin-top:0}.wcml-wrap .otgs-ico-yes,.wcml-wrap .otgs-ico-ok{color:#51a351}.wcml-wrap .otgs-ico-no,.wcml-wrap .otgs-ico-warning,.wcml-wrap .otgs-ico-delete{color:#9d261d}.wcml-wrap .otgs-ico-edit{color:#3a87ad}.wcml-wrap .otgs-ico-in-progress{color:#ffb800}@media (max-width: 1199px){.wcml-wrap .tablenav.top{height:auto}.wcml-wrap .tablenav.top.wcml-product-translation-filtering .alignright,.wcml-wrap .tablenav.top.wcml-product-translation-filtering .alignleft{float:none;margin-bottom:5px}}[class*="otgs-ico"]:before{font-size:16px}.wcml-tabs:before,.wcml-tabs:after{content:" ";display:table}.wcml-tabs:after{clear:both}.wcml-tabs .nav-tab{margin-top:5px}@media (max-width: 1350px){.wcml-tabs .nav-tab{margin-left:.2em}}.wcml-tabs .nav-tab [class*="otgs-ico"]:before{font-size:18px}.wcml-section{clear:both;padding:0 0 15px 0;margin:0 0 15px 0;border-bottom:1px solid #ededed}.wcml-section:after{content:'';display:table;clear:both}.wcml-section:last-of-type{border:none;margin:0}@media (max-width: 480px){.wcml-section .button{max-width:100%;white-space:normal;line-height:1.3;padding-top:7px;padding-bottom:8px;height:auto}}.explanation-text{color:#999}h4+.explanation-text{margin-top:-1.1em;margin-bottom:1.33em}.wcml-section-content .wcml-section-content-inner:not(:last-child){margin:0 0 20px 0;padding:0 0 10px 0;border-bottom:1px solid #ededed}.wcml-section-header h3{font-weight:normal;font-size:1.4em;margin-top:0.7em}.wcml-section-header h3 .wcml-tip:before{vertical-align:top}@media (min-width: 1200px){.wcml-section-header{width:310px;float:left}.wcml-section-content{float:left;width:600px;max-width:100%;margin-left:30px}.wcml-section-content-wide{width:calc(100% - 360px)}}.wcml_products{margin:20px 0;position:relative}.button-wrap,.widefat td .button-wrap{text-align:right;margin:10px 0}.currency_action_update{display:inline-block}.wcml-co-dialog.hidden{display:none}.wcml-co-dialog .wpml-form-row label,.wcml-co-dialog .wpml-form-row input,.wcml-co-dialog .wpml-form-row select{margin:3px 15px}.wcml-co-dialog .wpml-form-row label{width:215px;text-align:start}.wcml-co-dialog .wpml-form-row input,.wcml-co-dialog .wpml-form-row select{width:145px}.wcml-co-dialog .currency_code label{width:100px;vertical-align:top}.wcml-co-dialog .currency_code select{width:auto;max-width:calc(100% - 165px)}.wcml-co-dialog .wcml-co-exchange-rate label{width:100px;vertical-align:top}.wcml-co-dialog .wcml-co-exchange-rate input{margin:0 !important;width:75px}.wcml-co-dialog .wcml-co-exchange-rate .wcml-co-set-rate{display:inline-block;padding:4px 15px 7px 15px;max-width:265px}.wcml-co-dialog .wcml-co-exchange-rate small{display:block;margin-top:5px}.wcml-co-dialog .wcml-co-help-link{margin-top:7px}.wcml-co-dialog .wcml-co-preview label{width:120px;vertical-align:middle}.wcml-co-dialog .wcml-co-preview .wcml-co-preview-value{display:inline-block;padding:7px 15px;border:1px solid #555;font-size:1.4em;font-weight:bold;vertical-align:middle;margin:15px 0}.wcml-co-dialog .label-header{margin:20px 15px 7px 15px;display:block}.wcml-co-dialog .wcml-gateways-switcher{margin:7px 15px 30px}.wcml-co-dialog .wcml-gateways-switcher .otgs-toggle-group{display:inline-flex;-webkit-margin-end:15px;margin-inline-end:15px}.wcml-co-dialog .wcml-gateways{margin-bottom:30px}.wcml-co-dialog .wcml-gateways .wpml-form-row label{width:130px}.wcml-co-dialog .wcml-gateways .wpml-form-row input,.wcml-co-dialog .wcml-gateways .wpml-form-row select{width:auto}.wcml-co-dialog .wcml-gateways .wpml-form-row input+.wcml-tip,.wcml-co-dialog .wcml-gateways .wpml-form-row select+.wcml-tip{-webkit-margin-start:-12px;margin-inline-start:-12px}.wcml-co-dialog .wcml-gateways .explanation-text{display:block;margin:0 15px}table.widefat.currency_table{float:left;width:255px;border-right:none}@media (max-width: 782px){table.widefat.currency_table{width:120px}}table.widefat.currency_table td.wcml-col-currency,table.widefat.currency_table td.wcml-col-rate{padding-top:7px;padding-bottom:0;vertical-align:top}table.widefat.currency_table td.wcml-col-currency .truncate{max-width:100px;display:block}table.widefat.currency_table td.wcml-col-currency small{display:block}table.widefat.currency_table td.wcml-col-edit a{position:relative;top:-3px}table.widefat.currency_table td.wcml-col-rate{font-size:.85em;-webkit-padding-start:3px;padding-inline-start:3px}table.widefat.currency_table td.wcml-col-rate .truncate{max-width:75px;display:block}@media (max-width: 782px){table.widefat.currency_table .wcml-col-rate{display:none}}table.widefat.currency_settings_table{float:left;width:80px;border-left:none;clear:none}table.widefat.currency_settings_table td.wcml-col-delete,table.widefat.currency_settings_table td.wcml-col-edit{vertical-align:middle;text-align:center}table.widefat.currency_settings_table td.wcml-col-delete:first-child,table.widefat.currency_settings_table td.wcml-col-edit:first-child{border-left:1px solid #e5e5e5}.currency_value .wcml-error,.wcml-error{font-size:10px;color:#f00;display:inline-block}.trbl_variables_products{padding:10px;border:1px solid #8cceea;background-color:#eff8fc;border-radius:5px}.trbl_variables_products label span{font-weight:bold}.wcml_trbl_warning{padding:10px;margin-bottom:10px;border:1px solid #f00;background-color:#ffb7b7;border-radius:5px 5px}#wcml_sync_variations{background-color:#21759b;background-image:linear-gradient(to bottom, #2a95c5, #21759b);border-color:#21759b;border-bottom-color:#1e6a8d;box-shadow:inset 0 1px 0 rgba(120,200,230,0.5);color:#fff;text-decoration:none;text-shadow:0 1px 0 rgba(0,0,0,0.1)}.wcml_duplicate_product_notice td{border-bottom:none !important}.wcml_product_status_text,.prod_parent_text{font-style:italic;color:#9A9A9A}.wcml_no_found_text{text-align:center}.currency_languages{position:relative;text-align:center}.currency_languages:first-child{border-left:1px solid #e5e5e5}.currency_languages ul{margin:0;text-align:center}.currency_languages ul li{margin:0;display:none}.currency_languages ul li.on{display:inline-block}.currencies-table-content{display:inline-block;min-width:291px}@media (min-width: 1200px){.currencies-table-content{min-width:600px}}.currencies-table-content::after{display:table;clear:both;content:''}table.widefat.currency_lang_table{border-left:none;border-right:none}table.widefat.currency_lang_table thead .currency-lang-flags{height:23px}table.widefat.currency_lang_table thead tr{height:45px}table.widefat.currency_lang_table thead td{border-bottom:0;text-align:center;padding:3px 10px 1px 0;font-size:1em}table.widefat.currency_lang_table thead th{padding-top:0;padding-bottom:0;text-align:center}.currency_wrap{width:100%;max-width:calc(100% - 255px - 80px);min-width:70px;float:left;margin-bottom:10px;position:relative}.currency_wrap::after{content:'';position:absolute;top:1px;bottom:1px;right:0;width:15px;background:linear-gradient(to right, transparent, #fff)}@media (max-width: 782px){.currency_wrap{max-width:calc(100% - 121px - 80px)}}.currency_inner{overflow-x:auto;overflow-y:visible}.currency_table,.currency_lang_table,.currency_settings_table{clear:none}.currency_table thead tr,.currency_lang_table thead tr,.currency_settings_table thead tr{height:68px}.currency_table tr,.currency_lang_table tr,.currency_settings_table tr{height:50px}@media (max-width: 782px){.currency_table .default_currency,.currency_lang_table .default_currency,.currency_settings_table .default_currency{height:55px}}.currency_lang_table th{text-align:center}.currency_lang_table td{vertical-align:middle}.currency_lang_table.widefat td{padding-right:0;padding-left:0}@media (max-width: 782px){#wpbody .currency_lang_table select{font-size:10px}.currency_lang_table [class*='otgs-ico']::before{font-size:27px}}.default_currency select{font-size:9px;height:24px;margin:0;margin-right:2px;padding:2px 0}.default_currency td{border-top:1px solid #e5e5e5}.default_currency .inf_message{font-size:10px;font-style:italic;color:#9A9A9A}#wcml_currencies_order{display:block;overflow:hidden;width:100%}#wcml_currencies_order li{float:left;margin:2px 4px 2px 0;padding:2px 8px;border:1px solid #DFDFDF;border-radius:2px;background:linear-gradient(to top, #ECECEC, #F9F9F9) repeat scroll 0 0 #F1F1F1;cursor:move}.wcml_currencies_order_ajx_resp{font-weight:500;margin:0 5px;padding:1px 4px 2px;border-radius:3px;white-space:nowrap;color:#46b450;background-color:rgba(92,255,102,0.15)}.wcml-cs-list{font-size:inherit;width:100%;border-collapse:collapse;border:lightgrey 1px solid;vertical-align:middle}.wcml-cs-list thead tr{border:lightgrey 1px solid}.wcml-cs-list th,.wcml-cs-list td{text-align:center;padding:5px}.wcml-cs-list .wcml-cs-cell-preview{text-align:start}.wcml-cs-list .wcml-cs-actions{width:60px}.wcml-cs-list .wcml-cs-actions a{display:inline-block;width:20px;cursor:pointer}@media (max-width: 480px){.wcml-cs-list{display:block}.wcml-cs-list thead{display:none}.wcml-cs-list tbody,.wcml-cs-list tr:not(.wcml-cs-empty-row),.wcml-cs-list td{display:block !important;box-sizing:border-box}.wcml-cs-list tr::after{display:table;content:'';clear:both}.wcml-cs-list tr+tr{margin-top:30px}.wcml-cs-list .wcml-cs-cell-preview{width:100%}.wcml-cs-list .wcml-cs-widget-name,.wcml-cs-list .wcml-cs-actions{width:50%;float:left}.wcml-cs-list .wcml-cs-widget-name{text-align:start}.wcml-cs-list .wcml-cs-actions{text-align:end}}.wcml-currency-preview-wrapper{background-color:#fff;padding:15px 10px 10px;border:1px solid #ccc;width:100%;min-width:150px;min-height:120px;box-sizing:border-box;position:relative;display:flex !important;align-items:center;justify-content:center}.wcml-currency-preview-wrapper .wcml-currency-preview-label{position:absolute;top:5px;left:10px;z-index:101;display:inline-block;padding:2px;background:rgba(255,255,255,0.9)}.wcml-currency-preview-wrapper .spinner{position:absolute;bottom:5px;right:0;z-index:101}.wcml-cs-dialog .wcml-currency-switcher-options-form input{max-width:100%}@media (min-width: 1000px){.wcml-cs-dialog .wcml-currency-switcher-options-form{display:flex;flex-wrap:wrap;align-items:flex-start}.wcml-cs-dialog .wcml-currency-switcher-options-form .wcml-currency-switcher-options{width:60%;order:1;box-sizing:border-box}.wcml-cs-dialog .wcml-currency-switcher-options-form .wcml-currency-switcher-options>h4:first-child{margin-top:0}.wcml-cs-dialog .wcml-currency-switcher-options-form .wcml-currency-preview-wrapper{width:40%;box-sizing:border-box;order:2}.wcml-cs-dialog .wcml-currency-switcher-options-form .wcml-currency-preview-wrapper>div{display:block}}@media (max-width: 999px){.wcml-cs-dialog .wcml-currency-switcher-options-form .wcml-currency-preview-wrapper{margin:-17px -15px 30px -15px;width:calc(100% + 2 * 15px);border-left:0;border-right:0;z-index:10}}.wcml-cs-panel-colors table{width:100%;max-width:600px;font-size:inherit}.wcml-cs-panel-colors table th{text-align:start}.wcml-cs-panel-colors table td{vertical-align:top}.wcml-cs-panel-colors .wp-color-result,.wcml-cs-panel-colors .wp-color-result.button{padding-left:50px;position:relative}@media screen and (max-width: 782px){.wcml-cs-panel-colors .wp-color-result,.wcml-cs-panel-colors .wp-color-result.button{height:22px}}.wcml-cs-panel-colors .wp-color-result:after,.wcml-cs-panel-colors .wp-color-result.button:after{background:transparent;border-radius:0;border-left:0;padding:0;right:0;left:0;position:absolute;content:''}.wcml-cs-panel-colors .wp-color-result.wp-picker-open:after,.wcml-cs-panel-colors .wp-color-result.button.wp-picker-open:after{content:''}.wcml-cs-panel-colors .wp-color-result:not(.wp-picker-open):after,.wcml-cs-panel-colors .wp-color-result.button:not(.wp-picker-open):after{font-family:otgs-icons;content:'\69';color:#333;text-shadow:1px 1px 2px rgba(255,255,255,0.4);font-size:16px;min-width:0}.wcml-cs-panel-colors .wp-color-result.button .wp-color-result-text{display:none !important}.wcml-cs-panel-colors .wp-color-result.button:after{top:-2px}.wcml-cs-panel-colors .wp-picker-container input[type="text"].wp-color-picker{display:inline !important;margin-right:6px}.wcml_product_name{line-height:20px}.wcml_prod_filters{float:left}.wcml_miss_lang p:first-child{float:left}#display_custom_prices_select{display:inline-block;width:100%}.edit_slug_input,.edit_slug_hide_link{display:none}.wcml-tip{cursor:help;color:#555}.wcml-products a{cursor:pointer}@media (max-width: 782px){.column-product_cat,.column-product_tag,.column-product_type{display:none}}.wcml-link-troubleshooting{margin-top:7px}.wcml-status-list li{padding-left:25px;margin-bottom:30px}.wcml-status-list li ul li{margin-bottom:3.5px}.wcml-status-list.wcml-tax-translation-list li{margin-bottom:5px;line-height:26px}.wcml-status-list.wcml-plugins-status-list li{margin-bottom:10px}.wcml-status-list [class*="otgs-ico"]:not(.otgs-ico-help){margin-left:-25px;margin-right:5px;vertical-align:baseline}.wcml-status-list .button-secondary{vertical-align:middle}.wcml-status-list small{display:block}.wcml-lang-list{margin:7px 0}.wcml-lang-list .wpml-title-flag{margin-left:-25px;margin-right:5px}.wcml-dismiss-warning{position:relative;float:right;padding:0;text-decoration:none;outline:none}.wcml-dismiss-warning:active{outline:none}.wcml-notice{background:#fff;box-shadow:0 1px 1px 0 rgba(0,0,0,0.1);margin:5px 0 15px;padding:1px 12px;position:relative}.wcml-notice p{margin:.5em 0;padding:2px}.otgs-is-dismissible{position:relative;padding-right:38px}.otgs-is-dismissible .notice-dismiss{text-decoration:none}.otgs-is-dismissible p [class*="button-"]{margin:-5px 5px}.wcml_tt_spinner{margin-right:15px;display:none}.wcml-product-attributes-selector{text-align:center;margin-bottom:25px}@media (max-width: 1280px){.wcml-product-attributes-selector{margin-left:.2em}}.wcml-product-attributes-selector select{min-width:200px}.wcml-product-custom-taxonomies-selector{text-align:center;margin-bottom:25px}.wcml_attributes_wrap #wpml_tt_taxonomy_translation_wrap>label,.wcml_custom_taxonomies_wrap #wpml_tt_taxonomy_translation_wrap>label{display:none}
1
+ .wcml-wrap{border:1px solid #CCCCCC;padding:15px;background-color:#ffffff}.wcml-wrap:before,.wcml-wrap:after{content:" ";display:table}.wcml-wrap:after{clear:both}.dis_base{opacity:0.5}.display-block{display:block}.wcml-wrap{margin-bottom:20px}.wcml-wrap .wpml-tabs{margin-top:0}.wcml-wrap .otgs-ico-yes,.wcml-wrap .otgs-ico-ok{color:#51a351}.wcml-wrap .otgs-ico-no,.wcml-wrap .otgs-ico-warning,.wcml-wrap .otgs-ico-delete{color:#9d261d}.wcml-wrap .otgs-ico-edit{color:#3a87ad}.wcml-wrap .otgs-ico-in-progress{color:#ffb800}@media (max-width: 1199px){.wcml-wrap .tablenav.top{height:auto}.wcml-wrap .tablenav.top.wcml-product-translation-filtering .alignright,.wcml-wrap .tablenav.top.wcml-product-translation-filtering .alignleft{float:none;margin-bottom:5px}}[class*="otgs-ico"]:before{font-size:16px}.wcml-tabs:before,.wcml-tabs:after{content:" ";display:table}.wcml-tabs:after{clear:both}.wcml-tabs .nav-tab [class*="otgs-ico"]:before{font-size:18px}.wcml-tabs .nav-tab-active{background:#fff;border-bottom:none}.wcml-section{clear:both;padding:0 0 15px 0;margin:0 0 15px 0;border-bottom:1px solid #ededed}.wcml-section:after{content:'';display:table;clear:both}.wcml-section:last-of-type{border:none;margin:0}@media (max-width: 480px){.wcml-section .button{max-width:100%;white-space:normal;line-height:1.3;padding-top:7px;padding-bottom:8px;height:auto}}.explanation-text{color:#999}h4+.explanation-text{margin-top:-1.1em;margin-bottom:1.33em}.wcml-section-content .wcml-section-content-inner:not(:last-child){margin:0 0 20px 0;padding:0 0 10px 0;border-bottom:1px solid #ededed}.wcml-section-header h3{font-weight:normal;font-size:1.4em;margin-top:0.7em}.wcml-section-header h3 .wcml-tip:before{vertical-align:top}@media (min-width: 1200px){.wcml-section-header{width:310px;float:left}.wcml-section-content{float:left;width:600px;max-width:100%;margin-left:30px}.wcml-section-content-wide{width:calc(100% - 360px)}}.wcml_products{margin:20px 0;position:relative}.button-wrap,.widefat td .button-wrap{text-align:right;margin:10px 0}.currency_action_update{display:inline-block}.wcml-co-dialog.hidden{display:none}.wcml-co-dialog .wpml-form-row label,.wcml-co-dialog .wpml-form-row input,.wcml-co-dialog .wpml-form-row select{margin:3px 15px}.wcml-co-dialog .wpml-form-row label{width:215px;text-align:start}.wcml-co-dialog .wpml-form-row input,.wcml-co-dialog .wpml-form-row select{width:145px}.wcml-co-dialog .currency_code label{width:100px;vertical-align:top}.wcml-co-dialog .currency_code select{width:auto;max-width:calc(100% - 165px)}.wcml-co-dialog .wcml-co-exchange-rate label{width:100px;vertical-align:top}.wcml-co-dialog .wcml-co-exchange-rate input{margin:0 !important;width:75px}.wcml-co-dialog .wcml-co-exchange-rate .wcml-co-set-rate{display:inline-block;padding:4px 15px 7px 15px;max-width:265px}.wcml-co-dialog .wcml-co-exchange-rate small{display:block;margin-top:5px}.wcml-co-dialog .wcml-co-help-link{margin-top:7px}.wcml-co-dialog .wcml-co-preview label{width:120px;vertical-align:middle}.wcml-co-dialog .wcml-co-preview .wcml-co-preview-value{display:inline-block;padding:7px 15px;border:1px solid #555;font-size:1.4em;font-weight:bold;vertical-align:middle;margin:15px 0}.wcml-co-dialog .label-header{margin:20px 15px 7px 15px;display:block}.wcml-co-dialog .wcml-gateways-switcher{margin:7px 15px 30px}.wcml-co-dialog .wcml-gateways-switcher .otgs-toggle-group{display:inline-flex;-webkit-margin-end:15px;margin-inline-end:15px}.wcml-co-dialog .wcml-gateways{margin-bottom:30px}.wcml-co-dialog .wcml-gateways .wpml-form-row label{width:130px}.wcml-co-dialog .wcml-gateways .wpml-form-row input,.wcml-co-dialog .wcml-gateways .wpml-form-row select{width:auto}.wcml-co-dialog .wcml-gateways .wpml-form-row input+.wcml-tip,.wcml-co-dialog .wcml-gateways .wpml-form-row select+.wcml-tip{-webkit-margin-start:-12px;margin-inline-start:-12px}.wcml-co-dialog .wcml-gateways .explanation-text{display:block;margin:0 15px}table.widefat.currency_table{float:left;width:255px;border-right:none}@media (max-width: 782px){table.widefat.currency_table{width:120px}}table.widefat.currency_table td.wcml-col-currency,table.widefat.currency_table td.wcml-col-rate{padding-top:7px;padding-bottom:0;vertical-align:top}table.widefat.currency_table td.wcml-col-currency .truncate{max-width:100px;display:block}table.widefat.currency_table td.wcml-col-currency small{display:block}table.widefat.currency_table td.wcml-col-edit a{position:relative;top:-3px}table.widefat.currency_table td.wcml-col-rate{font-size:.85em;-webkit-padding-start:3px;padding-inline-start:3px}table.widefat.currency_table td.wcml-col-rate .truncate{max-width:75px;display:block}@media (max-width: 782px){table.widefat.currency_table .wcml-col-rate{display:none}}table.widefat.currency_settings_table{float:left;width:80px;border-left:none;clear:none}table.widefat.currency_settings_table td.wcml-col-delete,table.widefat.currency_settings_table td.wcml-col-edit{vertical-align:middle;text-align:center}table.widefat.currency_settings_table td.wcml-col-delete:first-child,table.widefat.currency_settings_table td.wcml-col-edit:first-child{border-left:1px solid #e5e5e5}.currency_value .wcml-error,.wcml-error{font-size:10px;color:#f00;display:inline-block}.trbl_variables_products{padding:10px;border:1px solid #8cceea;background-color:#eff8fc;border-radius:5px}.trbl_variables_products label span{font-weight:bold}.wcml_trbl_warning{padding:10px;margin-bottom:10px;border:1px solid #f00;background-color:#ffb7b7;border-radius:5px 5px}#wcml_sync_variations{background-color:#21759b;background-image:linear-gradient(to bottom, #2a95c5, #21759b);border-color:#21759b;border-bottom-color:#1e6a8d;box-shadow:inset 0 1px 0 rgba(120,200,230,0.5);color:#fff;text-decoration:none;text-shadow:0 1px 0 rgba(0,0,0,0.1)}.wcml_duplicate_product_notice td{border-bottom:none !important}.wcml_product_status_text,.prod_parent_text{font-style:italic;color:#9A9A9A}.wcml_no_found_text{text-align:center}.currency_languages{position:relative;text-align:center}.currency_languages:first-child{border-left:1px solid #e5e5e5}.currency_languages ul{margin:0;text-align:center}.currency_languages ul li{margin:0;display:none}.currency_languages ul li.on{display:inline-block}.currencies-table-content{display:inline-block;min-width:291px}@media (min-width: 1200px){.currencies-table-content{min-width:600px}}.currencies-table-content::after{display:table;clear:both;content:''}table.widefat.currency_lang_table{border-left:none;border-right:none}table.widefat.currency_lang_table thead .currency-lang-flags{height:23px}table.widefat.currency_lang_table thead tr{height:45px}table.widefat.currency_lang_table thead td{border-bottom:0;text-align:center;padding:3px 10px 1px 0;font-size:1em}table.widefat.currency_lang_table thead th{padding-top:0;padding-bottom:0;text-align:center}.currency_wrap{width:100%;max-width:calc(100% - 255px - 80px);min-width:70px;float:left;margin-bottom:10px;position:relative}.currency_wrap::after{content:'';position:absolute;top:1px;bottom:1px;right:0;width:15px;background:linear-gradient(to right, transparent, #fff)}@media (max-width: 782px){.currency_wrap{max-width:calc(100% - 121px - 80px)}}.currency_inner{overflow-x:auto;overflow-y:visible}.currency_table,.currency_lang_table,.currency_settings_table{clear:none}.currency_table thead tr,.currency_lang_table thead tr,.currency_settings_table thead tr{height:68px}.currency_table tr,.currency_lang_table tr,.currency_settings_table tr{height:50px}@media (max-width: 782px){.currency_table .default_currency,.currency_lang_table .default_currency,.currency_settings_table .default_currency{height:55px}}.currency_lang_table th{text-align:center}.currency_lang_table td{vertical-align:middle}.currency_lang_table.widefat td{padding-right:0;padding-left:0}@media (max-width: 782px){#wpbody .currency_lang_table select{font-size:10px}.currency_lang_table [class*='otgs-ico']::before{font-size:27px}}.default_currency select{font-size:9px;height:24px;margin:0;margin-right:2px;padding:2px 0}.default_currency td{border-top:1px solid #e5e5e5}.default_currency .inf_message{font-size:10px;font-style:italic;color:#9A9A9A}#wcml_currencies_order{display:block;overflow:hidden;width:100%}#wcml_currencies_order li{float:left;margin:2px 4px 2px 0;padding:2px 8px;border:1px solid #DFDFDF;border-radius:2px;background:linear-gradient(to top, #ECECEC, #F9F9F9) repeat scroll 0 0 #F1F1F1;cursor:move}.wcml_currencies_order_ajx_resp{font-weight:500;margin:0 5px;padding:1px 4px 2px;border-radius:3px;white-space:nowrap;color:#46b450;background-color:rgba(92,255,102,0.15)}.wcml-cs-list{font-size:inherit;width:100%;border-collapse:collapse;border:lightgrey 1px solid;vertical-align:middle}.wcml-cs-list thead tr{border:lightgrey 1px solid}.wcml-cs-list th,.wcml-cs-list td{text-align:center;padding:5px}.wcml-cs-list .wcml-cs-cell-preview{text-align:start}.wcml-cs-list .wcml-cs-actions{width:60px}.wcml-cs-list .wcml-cs-actions a{display:inline-block;width:20px;cursor:pointer}@media (max-width: 480px){.wcml-cs-list{display:block}.wcml-cs-list thead{display:none}.wcml-cs-list tbody,.wcml-cs-list tr:not(.wcml-cs-empty-row),.wcml-cs-list td{display:block !important;box-sizing:border-box}.wcml-cs-list tr::after{display:table;content:'';clear:both}.wcml-cs-list tr+tr{margin-top:30px}.wcml-cs-list .wcml-cs-cell-preview{width:100%}.wcml-cs-list .wcml-cs-widget-name,.wcml-cs-list .wcml-cs-actions{width:50%;float:left}.wcml-cs-list .wcml-cs-widget-name{text-align:start}.wcml-cs-list .wcml-cs-actions{text-align:end}}.wcml-currency-preview-wrapper{background-color:#fff;padding:15px 10px 10px;border:1px solid #ccc;width:100%;min-width:150px;min-height:120px;box-sizing:border-box;position:relative;display:flex !important;align-items:center;justify-content:center}.wcml-currency-preview-wrapper .wcml-currency-preview-label{position:absolute;top:5px;left:10px;z-index:101;display:inline-block;padding:2px;background:rgba(255,255,255,0.9)}.wcml-currency-preview-wrapper .spinner{position:absolute;bottom:5px;right:0;z-index:101}.wcml-cs-dialog .wcml-currency-switcher-options-form input{max-width:100%}@media (min-width: 1000px){.wcml-cs-dialog .wcml-currency-switcher-options-form{display:flex;flex-wrap:wrap;align-items:flex-start}.wcml-cs-dialog .wcml-currency-switcher-options-form .wcml-currency-switcher-options{width:60%;order:1;box-sizing:border-box}.wcml-cs-dialog .wcml-currency-switcher-options-form .wcml-currency-switcher-options>h4:first-child{margin-top:0}.wcml-cs-dialog .wcml-currency-switcher-options-form .wcml-currency-preview-wrapper{width:40%;box-sizing:border-box;order:2}.wcml-cs-dialog .wcml-currency-switcher-options-form .wcml-currency-preview-wrapper>div{display:block}}@media (max-width: 999px){.wcml-cs-dialog .wcml-currency-switcher-options-form .wcml-currency-preview-wrapper{margin:-17px -15px 30px -15px;width:calc(100% + 2 * 15px);border-left:0;border-right:0;z-index:10}}.wcml-cs-panel-colors table{width:100%;max-width:600px;font-size:inherit}.wcml-cs-panel-colors table th{text-align:start}.wcml-cs-panel-colors table td{vertical-align:top}.wcml-cs-panel-colors .wp-color-result,.wcml-cs-panel-colors .wp-color-result.button{padding-left:50px;position:relative}@media screen and (max-width: 782px){.wcml-cs-panel-colors .wp-color-result,.wcml-cs-panel-colors .wp-color-result.button{height:22px}}.wcml-cs-panel-colors .wp-color-result:after,.wcml-cs-panel-colors .wp-color-result.button:after{background:transparent;border-radius:0;border-left:0;padding:0;right:0;left:0;position:absolute;content:''}.wcml-cs-panel-colors .wp-color-result.wp-picker-open:after,.wcml-cs-panel-colors .wp-color-result.button.wp-picker-open:after{content:''}.wcml-cs-panel-colors .wp-color-result:not(.wp-picker-open):after,.wcml-cs-panel-colors .wp-color-result.button:not(.wp-picker-open):after{font-family:otgs-icons;content:'\69';color:#333;text-shadow:1px 1px 2px rgba(255,255,255,0.4);font-size:16px;min-width:0}.wcml-cs-panel-colors .wp-color-result.button .wp-color-result-text{display:none !important}.wcml-cs-panel-colors .wp-color-result.button:after{top:-2px}.wcml-cs-panel-colors .wp-picker-container input[type="text"].wp-color-picker{display:inline !important;margin-right:6px}.wcml_product_name{line-height:20px}.wcml_prod_filters{float:left}.wcml_miss_lang p:first-child{float:left}#display_custom_prices_select{display:inline-block;width:100%}.edit_slug_input,.edit_slug_hide_link{display:none}.wcml-tip{cursor:help;color:#555}.wcml-products a{cursor:pointer}@media (max-width: 782px){.column-product_cat,.column-product_tag,.column-product_type{display:none}}.wcml-link-troubleshooting{margin-top:7px}.wcml-status-list li{padding-left:25px;margin-bottom:30px}.wcml-status-list li ul li{margin-bottom:3.5px}.wcml-status-list.wcml-tax-translation-list li{margin-bottom:5px;line-height:26px}.wcml-status-list.wcml-plugins-status-list li{margin-bottom:10px}.wcml-status-list [class*="otgs-ico"]:not(.otgs-ico-help){margin-left:-25px;margin-right:5px;vertical-align:baseline}.wcml-status-list .button-secondary{vertical-align:middle}.wcml-status-list small{display:block}.wcml-lang-list{margin:7px 0}.wcml-lang-list .wpml-title-flag{margin-left:-25px;margin-right:5px}.wcml-dismiss-warning{position:relative;float:right;padding:0;text-decoration:none;outline:none}.wcml-dismiss-warning:active{outline:none}.wcml-notice{background:#fff;box-shadow:0 1px 1px 0 rgba(0,0,0,0.1);margin:5px 0 15px;padding:1px 12px;position:relative}.wcml-notice p{margin:.5em 0;padding:2px}.otgs-is-dismissible{position:relative;padding-right:38px}.otgs-is-dismissible .notice-dismiss{text-decoration:none}.otgs-is-dismissible p [class*="button-"]{margin:-5px 5px}.wcml_tt_spinner{margin-right:15px;display:none}.wcml-product-attributes-selector{text-align:center;margin-bottom:25px}@media (max-width: 1280px){.wcml-product-attributes-selector{margin-left:.2em}}.wcml-product-attributes-selector select{min-width:200px}.wcml-product-custom-taxonomies-selector{text-align:center;margin-bottom:25px}.wcml_attributes_wrap #wpml_tt_taxonomy_translation_wrap>label,.wcml_custom_taxonomies_wrap #wpml_tt_taxonomy_translation_wrap>label{display:none}
res/js/lock_fields.js CHANGED
@@ -7,6 +7,7 @@ jQuery(document).ready(function($){
7
  '_backorders',
8
  '_manage_stock',
9
  '_stock',
 
10
  '_stock_status',
11
  '_sold_individually',
12
  'comment_status',
@@ -167,6 +168,7 @@ var wcml_lock_variation_fields = function( file_path_sync ){
167
  '_sale_price_dates_from',
168
  '_sale_price_dates_to',
169
  '_stock',
 
170
  '_download_limit',
171
  '_download_expiry'
172
  ];
7
  '_backorders',
8
  '_manage_stock',
9
  '_stock',
10
+ '_low_stock_amount',
11
  '_stock_status',
12
  '_sold_individually',
13
  'comment_status',
168
  '_sale_price_dates_from',
169
  '_sale_price_dates_to',
170
  '_stock',
171
+ '_low_stock_amount',
172
  '_download_limit',
173
  '_download_expiry'
174
  ];
res/js/lock_fields.min.js CHANGED
@@ -1 +1 @@
1
- jQuery(document).ready(function($){var i;var ids=["_virtual","_downloadable","product-type","_backorders","_manage_stock","_stock","_stock_status","_sold_individually","comment_status","_tax_status","_tax_class","parent_id","crosssell_ids","upsell_ids","grouped_products","product_shipping_class"];if(unlock_fields.file_paths==1){ids.push("_download_type")}ids=ids.concat(non_standard_fields.ids);$(".wcml_prod_hidden_notice").prependTo("#woocommerce-product-data");for(i=0;i<ids.length;i++){$("#"+ids[i]).attr("disabled","disabled");$("#"+ids[i]).after($(".wcml_lock_img").clone().removeClass("wcml_lock_img").show())}var buttons=["add_variation","link_all_variations","attribute_taxonomy","save_attributes","add_new_attribute","product_attributes .remove_row","add_attribute","select_all_attributes","select_no_attributes","edit-visibility"];buttons=buttons.concat(non_standard_fields.classes);if(unlock_fields.file_paths==1){buttons.push("upload_file_button");buttons.push("insert");buttons.push("delete");$(".upload_file_button,.insert,.delete").bind({click:function(e){return false}})}for(i=0;i<buttons.length;i++){$("."+buttons[i]).attr("disabled","disabled");$("."+buttons[i]).after($(".wcml_lock_img").clone().removeClass("wcml_lock_img").show())}$("#visibility .edit-visibility span").bind({click:function(e){return false}});$(".remove_variation").each(function(){$(this).attr("disabled","disabled");$(this).after($(".wcml_lock_img").clone().removeClass("wcml_lock_img").show().css("float","right"))});var inpt_names=["_width","_height","_sku","_length","_weight","product_length","_regular_price","_sale_price","_sale_price_dates_from","_sale_price_dates_to"];if(unlock_fields.file_paths==1){inpt_names.push("_download_limit");inpt_names.push("_download_expiry");inpt_names.push("_wc_file_names[]");inpt_names.push("_wc_file_urls[]")}inpt_names=inpt_names.concat(non_standard_fields.input_names);if(unlock_fields.menu_order==1){inpt_names.push("menu_order")}for(i=0;i<inpt_names.length;i++){$('input[name="'+inpt_names[i]+'"]').attr("readonly","readonly");$(".dimensions_field span.wrap").css("float","left");if(inpt_names[i]=="_width"||inpt_names[i]=="_height"||inpt_names[i]=="_length"){$('input[name="'+inpt_names[i]+'"]').css("margin-right",0);$('input[name="'+inpt_names[i]+'"]').css("float","none");$('input[name="'+inpt_names[i]+'"]').css("width","29%")}if(inpt_names[i]=="_sale_price_dates_to"){$('input[name="'+inpt_names[i]+'"]').after($(".wcml_lock_img").clone().removeClass("wcml_lock_img").css("float","left").show())}else{$('input[name="'+inpt_names[i]+'"]').after($(".wcml_lock_img").clone().removeClass("wcml_lock_img").show())}}$('#product_attributes td textarea,#product_attributes input[type="text"]').each(function(){$(this).attr("readonly","readonly");$(this).after($(".wcml_lock_img").clone().removeClass("wcml_lock_img").show())});$('#product_attributes input[type="checkbox"],#_featured').each(function(){$(this).attr("disabled","disabled");$(this).after($(".wcml_lock_img").clone().removeClass("wcml_lock_img").show())});$('form#post input[type="submit"]').click(function(){for(i=0;i<ids.length;i++){$("#"+ids[i]).removeAttr("disabled")}$('.woocommerce_variation select,#variable_product_options .toolbar select,.woocommerce_variation input[type="checkbox"],#product_attributes input[type="checkbox"]').each(function(){$(this).removeAttr("disabled")})})});var wcml_lock_variation_fields=function(file_path_sync){var check_attr=jQuery(".woocommerce_variation>h3 select").attr("disabled");if(typeof check_attr!==typeof undefined&&check_attr!==false){return}jQuery(".woocommerce_variation>h3 select, #variable_product_options .toolbar select, .show_if_variation_manage_stock select").each(function(){jQuery(this).attr("disabled","disabled");jQuery(this).parent().append('<input type="hidden" name="'+jQuery(this).attr("name")+'" value="'+jQuery(this).val()+'" />');jQuery(this).after(jQuery(".wcml_lock_img").clone().removeClass("wcml_lock_img").show())});var i=0;var inpt_names=["_width","_height","_sku","_length","_weight","product_length","_regular_price","_sale_price","_sale_price_dates_from","_sale_price_dates_to","_stock","_download_limit","_download_expiry"];for(i=0;i<inpt_names.length;i++){jQuery('input[name^="variable'+inpt_names[i]+'"]').each(function(){jQuery(this).attr("readonly","readonly");jQuery(this).after(jQuery(".wcml_lock_img").clone().removeClass("wcml_lock_img").show())})}var var_checkboxes=["_enabled","_is_downloadable","_is_virtual","_manage_stock"];for(i=0;i<var_checkboxes.length;i++){jQuery('input[name^="variable'+var_checkboxes[i]+'"]').each(function(){jQuery(this).attr("disabled","disabled");if(jQuery(this).prop("checked")){jQuery(this).parent().append('<input type="hidden" name="'+jQuery(this).attr("name")+'" value="'+jQuery(this).val()+'" />')}jQuery(this).after(jQuery(".wcml_lock_img").clone().removeClass("wcml_lock_img").show())})}var var_selectboxes=["_stock_status","_shipping_class","_tax_class"];for(i=0;i<var_selectboxes.length;i++){jQuery('select[name^="variable'+var_selectboxes[i]+'"]').each(function(){jQuery(this).attr("disabled","disabled");jQuery(this).parent().append('<input type="hidden" name="'+jQuery(this).attr("name")+'" value="'+jQuery(this).val()+'" />');jQuery(this).after(jQuery(".wcml_lock_img").clone().removeClass("wcml_lock_img").show())})}if(file_path_sync){for(var key in file_path_sync){if(file_path_sync[key]==1){jQuery('input[name^="_wc_variation_file_names['+key+']"]').each(function(){jQuery(this).attr("readonly","readonly")});jQuery('input[name^="_wc_variation_file_urls['+key+']"]').each(function(){jQuery(this).attr("readonly","readonly");jQuery(this).closest("tr").find(".upload_file_button").attr("disabled","disabled");jQuery(this).closest("tr").find(".delete").attr("disabled","disabled");jQuery(this).closest("tr").find(".delete").after(jQuery(".wcml_lock_img").clone().removeClass("wcml_lock_img").show().css("float","right"))});jQuery('input[name^="_wc_variation_file_urls['+key+']"]').closest("table").find(".insert").attr("disabled","disabled");jQuery('input[name^="_wc_variation_file_urls['+key+']"]').closest("table").find(".insert").after(jQuery(".wcml_lock_img").clone().removeClass("wcml_lock_img").show().css("float","left"))}}}};
1
+ jQuery(document).ready(function($){var i;var ids=["_virtual","_downloadable","product-type","_backorders","_manage_stock","_stock","_low_stock_amount","_stock_status","_sold_individually","comment_status","_tax_status","_tax_class","parent_id","crosssell_ids","upsell_ids","grouped_products","product_shipping_class"];if(unlock_fields.file_paths==1){ids.push("_download_type")}ids=ids.concat(non_standard_fields.ids);$(".wcml_prod_hidden_notice").prependTo("#woocommerce-product-data");for(i=0;i<ids.length;i++){$("#"+ids[i]).attr("disabled","disabled");$("#"+ids[i]).after($(".wcml_lock_img").clone().removeClass("wcml_lock_img").show())}var buttons=["add_variation","link_all_variations","attribute_taxonomy","save_attributes","add_new_attribute","product_attributes .remove_row","add_attribute","select_all_attributes","select_no_attributes","edit-visibility"];buttons=buttons.concat(non_standard_fields.classes);if(unlock_fields.file_paths==1){buttons.push("upload_file_button");buttons.push("insert");buttons.push("delete");$(".upload_file_button,.insert,.delete").bind({click:function(e){return false}})}for(i=0;i<buttons.length;i++){$("."+buttons[i]).attr("disabled","disabled");$("."+buttons[i]).after($(".wcml_lock_img").clone().removeClass("wcml_lock_img").show())}$("#visibility .edit-visibility span").bind({click:function(e){return false}});$(".remove_variation").each(function(){$(this).attr("disabled","disabled");$(this).after($(".wcml_lock_img").clone().removeClass("wcml_lock_img").show().css("float","right"))});var inpt_names=["_width","_height","_sku","_length","_weight","product_length","_regular_price","_sale_price","_sale_price_dates_from","_sale_price_dates_to"];if(unlock_fields.file_paths==1){inpt_names.push("_download_limit");inpt_names.push("_download_expiry");inpt_names.push("_wc_file_names[]");inpt_names.push("_wc_file_urls[]")}inpt_names=inpt_names.concat(non_standard_fields.input_names);if(unlock_fields.menu_order==1){inpt_names.push("menu_order")}for(i=0;i<inpt_names.length;i++){$('input[name="'+inpt_names[i]+'"]').attr("readonly","readonly");$(".dimensions_field span.wrap").css("float","left");if(inpt_names[i]=="_width"||inpt_names[i]=="_height"||inpt_names[i]=="_length"){$('input[name="'+inpt_names[i]+'"]').css("margin-right",0);$('input[name="'+inpt_names[i]+'"]').css("float","none");$('input[name="'+inpt_names[i]+'"]').css("width","29%")}if(inpt_names[i]=="_sale_price_dates_to"){$('input[name="'+inpt_names[i]+'"]').after($(".wcml_lock_img").clone().removeClass("wcml_lock_img").css("float","left").show())}else{$('input[name="'+inpt_names[i]+'"]').after($(".wcml_lock_img").clone().removeClass("wcml_lock_img").show())}}$('#product_attributes td textarea,#product_attributes input[type="text"]').each(function(){$(this).attr("readonly","readonly");$(this).after($(".wcml_lock_img").clone().removeClass("wcml_lock_img").show())});$('#product_attributes input[type="checkbox"],#_featured').each(function(){$(this).attr("disabled","disabled");$(this).after($(".wcml_lock_img").clone().removeClass("wcml_lock_img").show())});$('form#post input[type="submit"]').click(function(){for(i=0;i<ids.length;i++){$("#"+ids[i]).removeAttr("disabled")}$('.woocommerce_variation select,#variable_product_options .toolbar select,.woocommerce_variation input[type="checkbox"],#product_attributes input[type="checkbox"]').each(function(){$(this).removeAttr("disabled")})})});var wcml_lock_variation_fields=function(file_path_sync){var check_attr=jQuery(".woocommerce_variation>h3 select").attr("disabled");if(typeof check_attr!==typeof undefined&&check_attr!==false){return}jQuery(".woocommerce_variation>h3 select, #variable_product_options .toolbar select, .show_if_variation_manage_stock select").each(function(){jQuery(this).attr("disabled","disabled");jQuery(this).parent().append('<input type="hidden" name="'+jQuery(this).attr("name")+'" value="'+jQuery(this).val()+'" />');jQuery(this).after(jQuery(".wcml_lock_img").clone().removeClass("wcml_lock_img").show())});var i=0;var inpt_names=["_width","_height","_sku","_length","_weight","product_length","_regular_price","_sale_price","_sale_price_dates_from","_sale_price_dates_to","_stock","_low_stock_amount","_download_limit","_download_expiry"];for(i=0;i<inpt_names.length;i++){jQuery('input[name^="variable'+inpt_names[i]+'"]').each(function(){jQuery(this).attr("readonly","readonly");jQuery(this).after(jQuery(".wcml_lock_img").clone().removeClass("wcml_lock_img").show())})}var var_checkboxes=["_enabled","_is_downloadable","_is_virtual","_manage_stock"];for(i=0;i<var_checkboxes.length;i++){jQuery('input[name^="variable'+var_checkboxes[i]+'"]').each(function(){jQuery(this).attr("disabled","disabled");if(jQuery(this).prop("checked")){jQuery(this).parent().append('<input type="hidden" name="'+jQuery(this).attr("name")+'" value="'+jQuery(this).val()+'" />')}jQuery(this).after(jQuery(".wcml_lock_img").clone().removeClass("wcml_lock_img").show())})}var var_selectboxes=["_stock_status","_shipping_class","_tax_class"];for(i=0;i<var_selectboxes.length;i++){jQuery('select[name^="variable'+var_selectboxes[i]+'"]').each(function(){jQuery(this).attr("disabled","disabled");jQuery(this).parent().append('<input type="hidden" name="'+jQuery(this).attr("name")+'" value="'+jQuery(this).val()+'" />');jQuery(this).after(jQuery(".wcml_lock_img").clone().removeClass("wcml_lock_img").show())})}if(file_path_sync){for(var key in file_path_sync){if(file_path_sync[key]==1){jQuery('input[name^="_wc_variation_file_names['+key+']"]').each(function(){jQuery(this).attr("readonly","readonly")});jQuery('input[name^="_wc_variation_file_urls['+key+']"]').each(function(){jQuery(this).attr("readonly","readonly");jQuery(this).closest("tr").find(".upload_file_button").attr("disabled","disabled");jQuery(this).closest("tr").find(".delete").attr("disabled","disabled");jQuery(this).closest("tr").find(".delete").after(jQuery(".wcml_lock_img").clone().removeClass("wcml_lock_img").show().css("float","right"))});jQuery('input[name^="_wc_variation_file_urls['+key+']"]').closest("table").find(".insert").attr("disabled","disabled");jQuery('input[name^="_wc_variation_file_urls['+key+']"]').closest("table").find(".insert").after(jQuery(".wcml_lock_img").clone().removeClass("wcml_lock_img").show().css("float","left"))}}}};
res/js/troubleshooting.js CHANGED
@@ -184,6 +184,36 @@ jQuery( function($) {
184
  });
185
  },
186
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
187
  fix_product_type_terms: function(){
188
  jQuery.ajax({
189
  type : "post",
@@ -216,6 +246,8 @@ jQuery( function($) {
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();
184
  });
185
  },
186
 
187
+ fix_translated_variations_relationships: function(){
188
+ jQuery.ajax({
189
+ type : "post",
190
+ url : ajaxurl,
191
+ data : {
192
+ action: "fix_translated_variations_relationships",
193
+ wcml_nonce: jQuery('#fix_relationships_nonce').val()
194
+ },
195
+ dataType: 'json',
196
+ success: function(response) {
197
+
198
+ var count_input = jQuery('#count_relationships');
199
+
200
+ if( count_input.val() == 0 ){
201
+ WCML_Troubleshooting.run_next_troubleshooting_action();
202
+ jQuery('.relationships_status').html(0);
203
+ }else{
204
+ var left = count_input.val()-5;
205
+ if(left < 0 ){
206
+ left = 0;
207
+ }
208
+ jQuery('.relationships_status').html(left);
209
+ count_input.val(left);
210
+
211
+ WCML_Troubleshooting.fix_translated_variations_relationships();
212
+ }
213
+ }
214
+ });
215
+ },
216
+
217
  fix_product_type_terms: function(){
218
  jQuery.ajax({
219
  type : "post",
246
  WCML_Troubleshooting.duplicate_terms();
247
  }else if(jQuery('#wcml_sync_stock').is(':checked') && parseInt( jQuery('#count_stock').val() ) !== 0 ){
248
  WCML_Troubleshooting.sync_stock();
249
+ }else if(jQuery('#wcml_fix_relationships').is(':checked') && parseInt( jQuery('#count_relationships').val() ) !== 0 ){
250
+ WCML_Troubleshooting.fix_translated_variations_relationships();
251
  }else{
252
  jQuery('#wcml_trbl').removeAttr('disabled');
253
  jQuery('.spinner').hide();
res/js/troubleshooting.min.js CHANGED
@@ -1 +1 @@
1
- jQuery(function($){WCML_Troubleshooting={init:function(){$(document).ready(function(){jQuery("#wcml_trbl").on("click",function(){var field=jQuery(this);field.attr("disabled","disabled");jQuery(".spinner").css("display","inline-block").css("visibility","visible");if(jQuery("#wcml_sync_update_product_count").is(":checked")){WCML_Troubleshooting.update_product_count()}else{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 field=jQuery(this);field.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(response){jQuery(".var_status").each(function(){jQuery(this).html(response.data.count)});jQuery("#count_prod_variat").val(response.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(response){if(jQuery("#count_prod_variat").val()==0){jQuery(".var_status").each(function(){jQuery(this).html(0)});WCML_Troubleshooting.run_next_troubleshooting_action()}else{var left=jQuery("#count_prod_variat").val()-3;if(left<0){left=0}jQuery(".var_status").each(function(){jQuery(this).html(left)});jQuery("#count_prod_variat").val(left);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(response){if(jQuery("#count_galleries").val()==0){WCML_Troubleshooting.run_next_troubleshooting_action();jQuery(".gallery_status").html(0)}else{var left=jQuery("#count_galleries").val()-5;if(left<0){left=0}else{jQuery("#sync_galerry_page").val(parseInt(jQuery("#sync_galerry_page").val())+1)}jQuery(".gallery_status").html(left);jQuery("#count_galleries").val(left);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(response){if(jQuery("#count_categories").val()==0){WCML_Troubleshooting.run_next_troubleshooting_action();jQuery(".cat_status").html(0)}else{var left=jQuery("#count_categories").val()-5;if(left<0){left=0}else{jQuery("#sync_category_page").val(parseInt(jQuery("#sync_category_page").val())+1)}jQuery(".cat_status").html(left);jQuery("#count_categories").val(left);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(response){if(jQuery("#count_terms").val()==0){WCML_Troubleshooting.run_next_troubleshooting_action();jQuery(".attr_status").html(0)}else{var left=jQuery("#count_terms").val()-5;if(left<0){left=0}jQuery(".attr_status").html(left);jQuery("#count_terms").val(left);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(response){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(response){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(){if(jQuery("#wcml_sync_product_variations").is(":checked")&&parseInt(jQuery("#count_prod_variat").val())!==0){WCML_Troubleshooting.sync_variations()}else if(jQuery("#wcml_sync_gallery_images").is(":checked")&&parseInt(jQuery("#count_galleries").val())!==0){WCML_Troubleshooting.sync_product_gallery()}else if(jQuery("#wcml_sync_categories").is(":checked")&&parseInt(jQuery("#count_categories").val())!==0){WCML_Troubleshooting.sync_product_categories()}else if(jQuery("#wcml_duplicate_terms").is(":checked")&&parseInt(jQuery("#count_terms").val())!==0){WCML_Troubleshooting.duplicate_terms()}else if(jQuery("#wcml_sync_stock").is(":checked")&&parseInt(jQuery("#count_stock").val())!==0){WCML_Troubleshooting.sync_stock()}else{jQuery("#wcml_trbl").removeAttr("disabled");jQuery(".spinner").hide();jQuery("#wcml_trbl").next().fadeOut()}}};WCML_Troubleshooting.init()});
1
+ jQuery(function($){WCML_Troubleshooting={init:function(){$(document).ready(function(){jQuery("#wcml_trbl").on("click",function(){var field=jQuery(this);field.attr("disabled","disabled");jQuery(".spinner").css("display","inline-block").css("visibility","visible");if(jQuery("#wcml_sync_update_product_count").is(":checked")){WCML_Troubleshooting.update_product_count()}else{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 field=jQuery(this);field.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(response){jQuery(".var_status").each(function(){jQuery(this).html(response.data.count)});jQuery("#count_prod_variat").val(response.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(response){if(jQuery("#count_prod_variat").val()==0){jQuery(".var_status").each(function(){jQuery(this).html(0)});WCML_Troubleshooting.run_next_troubleshooting_action()}else{var left=jQuery("#count_prod_variat").val()-3;if(left<0){left=0}jQuery(".var_status").each(function(){jQuery(this).html(left)});jQuery("#count_prod_variat").val(left);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(response){if(jQuery("#count_galleries").val()==0){WCML_Troubleshooting.run_next_troubleshooting_action();jQuery(".gallery_status").html(0)}else{var left=jQuery("#count_galleries").val()-5;if(left<0){left=0}else{jQuery("#sync_galerry_page").val(parseInt(jQuery("#sync_galerry_page").val())+1)}jQuery(".gallery_status").html(left);jQuery("#count_galleries").val(left);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(response){if(jQuery("#count_categories").val()==0){WCML_Troubleshooting.run_next_troubleshooting_action();jQuery(".cat_status").html(0)}else{var left=jQuery("#count_categories").val()-5;if(left<0){left=0}else{jQuery("#sync_category_page").val(parseInt(jQuery("#sync_category_page").val())+1)}jQuery(".cat_status").html(left);jQuery("#count_categories").val(left);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(response){if(jQuery("#count_terms").val()==0){WCML_Troubleshooting.run_next_troubleshooting_action();jQuery(".attr_status").html(0)}else{var left=jQuery("#count_terms").val()-5;if(left<0){left=0}jQuery(".attr_status").html(left);jQuery("#count_terms").val(left);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(response){jQuery("#count_stock").val(0);WCML_Troubleshooting.run_next_troubleshooting_action();jQuery(".stock_status").html(0)}})},fix_translated_variations_relationships:function(){jQuery.ajax({type:"post",url:ajaxurl,data:{action:"fix_translated_variations_relationships",wcml_nonce:jQuery("#fix_relationships_nonce").val()},dataType:"json",success:function(response){var count_input=jQuery("#count_relationships");if(count_input.val()==0){WCML_Troubleshooting.run_next_troubleshooting_action();jQuery(".relationships_status").html(0)}else{var left=count_input.val()-5;if(left<0){left=0}jQuery(".relationships_status").html(left);count_input.val(left);WCML_Troubleshooting.fix_translated_variations_relationships()}}})},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(response){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(){if(jQuery("#wcml_sync_product_variations").is(":checked")&&parseInt(jQuery("#count_prod_variat").val())!==0){WCML_Troubleshooting.sync_variations()}else if(jQuery("#wcml_sync_gallery_images").is(":checked")&&parseInt(jQuery("#count_galleries").val())!==0){WCML_Troubleshooting.sync_product_gallery()}else if(jQuery("#wcml_sync_categories").is(":checked")&&parseInt(jQuery("#count_categories").val())!==0){WCML_Troubleshooting.sync_product_categories()}else if(jQuery("#wcml_duplicate_terms").is(":checked")&&parseInt(jQuery("#count_terms").val())!==0){WCML_Troubleshooting.duplicate_terms()}else if(jQuery("#wcml_sync_stock").is(":checked")&&parseInt(jQuery("#count_stock").val())!==0){WCML_Troubleshooting.sync_stock()}else if(jQuery("#wcml_fix_relationships").is(":checked")&&parseInt(jQuery("#count_relationships").val())!==0){WCML_Troubleshooting.fix_translated_variations_relationships()}else{jQuery("#wcml_trbl").removeAttr("disabled");jQuery(".spinner").hide();jQuery("#wcml_trbl").next().fadeOut()}}};WCML_Troubleshooting.init()});
templates/multi-currency/exchange-rates.twig CHANGED
@@ -49,15 +49,12 @@
49
  </a>
50
  <div class="service-details-wrap" {% if exchange_rates.settings.service != id %} style="display: none;"{% endif %} >
51
 
52
- {% if service.requires_key %}
53
-
54
  {{ exchange_rates.strings.key_required }}
55
  <input type="text" name="services[{{ id }}][api-key]"
56
  value="{{ service.api_key }}"
57
  placeholder="{{ exchange_rates.strings.key_placeholder }}"
58
  size="40" />
59
 
60
- {% endif %}
61
  <p class="notice inline notice-error" {% if 'fixerio' != id %}style="display:none"{% endif %}>
62
  {{ exchange_rates.strings.fixerio_warning }}
63
  </p>
49
  </a>
50
  <div class="service-details-wrap" {% if exchange_rates.settings.service != id %} style="display: none;"{% endif %} >
51
 
 
 
52
  {{ exchange_rates.strings.key_required }}
53
  <input type="text" name="services[{{ id }}][api-key]"
54
  value="{{ service.api_key }}"
55
  placeholder="{{ exchange_rates.strings.key_placeholder }}"
56
  size="40" />
57
 
 
58
  <p class="notice inline notice-error" {% if 'fixerio' != id %}style="display:none"{% endif %}>
59
  {{ exchange_rates.strings.fixerio_warning }}
60
  </p>
templates/troubleshooting.twig CHANGED
@@ -73,6 +73,14 @@
73
  <span>{{ strings.left }}</span>
74
  </label>
75
  </li>
 
 
 
 
 
 
 
 
76
  <li>
77
  <button type="button" class="button-secondary" id="wcml_trbl">{{ strings.start }}</button>
78
  <input id="count_prod_variat" type="hidden" value="{{ prod_with_variations }}"/>
@@ -81,6 +89,7 @@
81
  <input id="count_categories" type="hidden" value="{{ prod_categories_count }}"/>
82
  <input id="count_terms" type="hidden" value="{{ terms_count }}"/>
83
  <input id="count_stock" type="hidden" value="{{ sync_stock_count }}"/>
 
84
  <input id="sync_galerry_page" type="hidden" value="0"/>
85
  <input id="sync_category_page" type="hidden" value="0"/>
86
  <span class="spinner"></span>
@@ -90,6 +99,7 @@
90
  {{ nonces.trbl_sync_categories|raw }}
91
  {{ nonces.trbl_duplicate_terms|raw }}
92
  {{ nonces.trbl_sync_stock|raw }}
 
93
  </li>
94
  </ul>
95
  {% if product_type_sync_needed %}
73
  <span>{{ strings.left }}</span>
74
  </label>
75
  </li>
76
+ <li>
77
+ <label>
78
+ <input type="checkbox" id="wcml_fix_relationships" />
79
+ {{ strings.sync_relationships }}
80
+ <span class="relationships_status">{{ fix_relationships_count }}</span>
81
+ <span>{{ strings.left }}</span>
82
+ </label>
83
+ </li>
84
  <li>
85
  <button type="button" class="button-secondary" id="wcml_trbl">{{ strings.start }}</button>
86
  <input id="count_prod_variat" type="hidden" value="{{ prod_with_variations }}"/>
89
  <input id="count_categories" type="hidden" value="{{ prod_categories_count }}"/>
90
  <input id="count_terms" type="hidden" value="{{ terms_count }}"/>
91
  <input id="count_stock" type="hidden" value="{{ sync_stock_count }}"/>
92
+ <input id="count_relationships" type="hidden" value="{{ fix_relationships_count }}"/>
93
  <input id="sync_galerry_page" type="hidden" value="0"/>
94
  <input id="sync_category_page" type="hidden" value="0"/>
95
  <span class="spinner"></span>
99
  {{ nonces.trbl_sync_categories|raw }}
100
  {{ nonces.trbl_duplicate_terms|raw }}
101
  {{ nonces.trbl_sync_stock|raw }}
102
+ {{ nonces.fix_relationships|raw }}
103
  </li>
104
  </ul>
105
  {% 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 ComposerAutoloaderInit4dd7b8af9819cda305271fc30af4e92e::getLoader();
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
+ return ComposerAutoloaderInitdd99bdc714d3a0da336f7270f9054514::getLoader();
vendor/autoload_52.php CHANGED
@@ -4,4 +4,4 @@
4
 
5
  require_once dirname(__FILE__) . '/composer'.'/autoload_real_52.php';
6
 
7
- return ComposerAutoloaderInit9f4cbe4e044be3ae24be4934f9665025::getLoader();
4
 
5
  require_once dirname(__FILE__) . '/composer'.'/autoload_real_52.php';
6
 
7
+ return ComposerAutoloaderInit077a9de49a58a2d7a901028b88774abf::getLoader();
vendor/composer/autoload_classmap.php CHANGED
@@ -6,6 +6,7 @@ $vendorDir = dirname(dirname(__FILE__));
6
  $baseDir = dirname($vendorDir);
7
 
8
  return array(
 
9
  'WCML_Accommodation_Bookings' => $baseDir . '/compatibility/class-wcml-accommodation-bookings.php',
10
  'WCML_Admin_Cookie' => $baseDir . '/classes/class-wcml-admin-cookie.php',
11
  'WCML_Admin_Currency_Selector' => $baseDir . '/classes/currencies/class-wcml-admin-currency-selector.php',
@@ -173,7 +174,7 @@ return array(
173
  'WCML_Upgrade' => $baseDir . '/inc/class-wcml-upgrade.php',
174
  'WCML_Url_Filters_Redirect_Location' => $baseDir . '/classes/url-filters/class-wcml-url-filters-redirect-location.php',
175
  'WCML_Url_Translation' => $baseDir . '/inc/class-wcml-url-translation.php',
176
- 'WCML_Variation_Swatches_and_Photos' => $baseDir . '/compatibility/class-wcml-variation-swatches-and-photos.php',
177
  'WCML_Vpc' => $baseDir . '/compatibility/class-wcml-vpc.php',
178
  'WCML_W3TC_Multi_Currency' => $baseDir . '/inc/currencies/class-wcml-w3tc-multi-currency.php',
179
  'WCML_WC_Admin_Duplicate_Product' => $baseDir . '/inc/translation-editor/class-wcml-wc-admin-duplicate-product.php',
@@ -192,9 +193,12 @@ return array(
192
  'WCML_Woo_Var_Table' => $baseDir . '/compatibility/class-wcml-woo-var-table.php',
193
  'WCML_WpFastest_Cache' => $baseDir . '/compatibility/class-wcml-wpfastest-cache.php',
194
  'WCML_Wpb_Vc' => $baseDir . '/compatibility/class-wcml-wpb-vc.php',
 
195
  'WCML_YITH_WCQV' => $baseDir . '/compatibility/class-wcml-yith-wcqv.php',
196
  'WCML_gravityforms' => $baseDir . '/compatibility/class-wcml-gravityforms.php',
197
  'WCML_wcExporter' => $baseDir . '/compatibility/class-wcml-wcexporter.php',
198
  'WCML_xDomain_Data' => $baseDir . '/classes/urls/class-wcml-xdomain-data.php',
 
 
199
  'woocommerce_wpml' => $baseDir . '/classes/class-woocommerce-wpml.php',
200
  );
6
  $baseDir = dirname($vendorDir);
7
 
8
  return array(
9
+ 'WCML_ATE_Activate_Synchronization' => $baseDir . '/classes/ate/class-wcml-ate-activate-synchronization.php',
10
  'WCML_Accommodation_Bookings' => $baseDir . '/compatibility/class-wcml-accommodation-bookings.php',
11
  'WCML_Admin_Cookie' => $baseDir . '/classes/class-wcml-admin-cookie.php',
12
  'WCML_Admin_Currency_Selector' => $baseDir . '/classes/currencies/class-wcml-admin-currency-selector.php',
174
  'WCML_Upgrade' => $baseDir . '/inc/class-wcml-upgrade.php',
175
  'WCML_Url_Filters_Redirect_Location' => $baseDir . '/classes/url-filters/class-wcml-url-filters-redirect-location.php',
176
  'WCML_Url_Translation' => $baseDir . '/inc/class-wcml-url-translation.php',
177
+ 'WCML_Variation_Swatches_And_Photos' => $baseDir . '/compatibility/class-wcml-variation-swatches-and-photos.php',
178
  'WCML_Vpc' => $baseDir . '/compatibility/class-wcml-vpc.php',
179
  'WCML_W3TC_Multi_Currency' => $baseDir . '/inc/currencies/class-wcml-w3tc-multi-currency.php',
180
  'WCML_WC_Admin_Duplicate_Product' => $baseDir . '/inc/translation-editor/class-wcml-wc-admin-duplicate-product.php',
193
  'WCML_Woo_Var_Table' => $baseDir . '/compatibility/class-wcml-woo-var-table.php',
194
  'WCML_WpFastest_Cache' => $baseDir . '/compatibility/class-wcml-wpfastest-cache.php',
195
  'WCML_Wpb_Vc' => $baseDir . '/compatibility/class-wcml-wpb-vc.php',
196
+ 'WCML_YIKES_Custom_Product_Tabs_Pro' => $baseDir . '/compatibility/class-wcml-yikes-custom-product-tabs-pro.php',
197
  'WCML_YITH_WCQV' => $baseDir . '/compatibility/class-wcml-yith-wcqv.php',
198
  'WCML_gravityforms' => $baseDir . '/compatibility/class-wcml-gravityforms.php',
199
  'WCML_wcExporter' => $baseDir . '/compatibility/class-wcml-wcexporter.php',
200
  'WCML_xDomain_Data' => $baseDir . '/classes/urls/class-wcml-xdomain-data.php',
201
+ 'WPML_Core_Version_Check' => $vendorDir . '/wpml-shared/wpml-lib-dependencies/src/dependencies/class-wpml-core-version-check.php',
202
+ 'WPML_Dependencies' => $vendorDir . '/wpml-shared/wpml-lib-dependencies/src/dependencies/class-wpml-dependencies.php',
203
  'woocommerce_wpml' => $baseDir . '/classes/class-woocommerce-wpml.php',
204
  );
vendor/composer/autoload_real.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
- class ComposerAutoloaderInit4dd7b8af9819cda305271fc30af4e92e
6
  {
7
  private static $loader;
8
 
@@ -19,15 +19,15 @@ class ComposerAutoloaderInit4dd7b8af9819cda305271fc30af4e92e
19
  return self::$loader;
20
  }
21
 
22
- spl_autoload_register(array('ComposerAutoloaderInit4dd7b8af9819cda305271fc30af4e92e', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
- spl_autoload_unregister(array('ComposerAutoloaderInit4dd7b8af9819cda305271fc30af4e92e', '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\ComposerStaticInit4dd7b8af9819cda305271fc30af4e92e::getInitializer($loader));
31
  } else {
32
  $map = require __DIR__ . '/autoload_namespaces.php';
33
  foreach ($map as $namespace => $path) {
@@ -48,19 +48,19 @@ class ComposerAutoloaderInit4dd7b8af9819cda305271fc30af4e92e
48
  $loader->register(true);
49
 
50
  if ($useStaticLoader) {
51
- $includeFiles = Composer\Autoload\ComposerStaticInit4dd7b8af9819cda305271fc30af4e92e::$files;
52
  } else {
53
  $includeFiles = require __DIR__ . '/autoload_files.php';
54
  }
55
  foreach ($includeFiles as $fileIdentifier => $file) {
56
- composerRequire4dd7b8af9819cda305271fc30af4e92e($fileIdentifier, $file);
57
  }
58
 
59
  return $loader;
60
  }
61
  }
62
 
63
- function composerRequire4dd7b8af9819cda305271fc30af4e92e($fileIdentifier, $file)
64
  {
65
  if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
66
  require $file;
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
+ class ComposerAutoloaderInitdd99bdc714d3a0da336f7270f9054514
6
  {
7
  private static $loader;
8
 
19
  return self::$loader;
20
  }
21
 
22
+ spl_autoload_register(array('ComposerAutoloaderInitdd99bdc714d3a0da336f7270f9054514', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInitdd99bdc714d3a0da336f7270f9054514', '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\ComposerStaticInitdd99bdc714d3a0da336f7270f9054514::getInitializer($loader));
31
  } else {
32
  $map = require __DIR__ . '/autoload_namespaces.php';
33
  foreach ($map as $namespace => $path) {
48
  $loader->register(true);
49
 
50
  if ($useStaticLoader) {
51
+ $includeFiles = Composer\Autoload\ComposerStaticInitdd99bdc714d3a0da336f7270f9054514::$files;
52
  } else {
53
  $includeFiles = require __DIR__ . '/autoload_files.php';
54
  }
55
  foreach ($includeFiles as $fileIdentifier => $file) {
56
+ composerRequiredd99bdc714d3a0da336f7270f9054514($fileIdentifier, $file);
57
  }
58
 
59
  return $loader;
60
  }
61
  }
62
 
63
+ function composerRequiredd99bdc714d3a0da336f7270f9054514($fileIdentifier, $file)
64
  {
65
  if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
66
  require $file;
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 ComposerAutoloaderInit9f4cbe4e044be3ae24be4934f9665025 {
6
  private static $loader;
7
 
8
  public static function loadClassLoader($class) {
@@ -19,9 +19,9 @@ class ComposerAutoloaderInit9f4cbe4e044be3ae24be4934f9665025 {
19
  return self::$loader;
20
  }
21
 
22
- spl_autoload_register(array('ComposerAutoloaderInit9f4cbe4e044be3ae24be4934f9665025', 'loadClassLoader'), true /*, true */);
23
  self::$loader = $loader = new xrstf_Composer52_ClassLoader();
24
- spl_autoload_unregister(array('ComposerAutoloaderInit9f4cbe4e044be3ae24be4934f9665025', '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 ComposerAutoloaderInit077a9de49a58a2d7a901028b88774abf {
6
  private static $loader;
7
 
8
  public static function loadClassLoader($class) {
19
  return self::$loader;
20
  }
21
 
22
+ spl_autoload_register(array('ComposerAutoloaderInit077a9de49a58a2d7a901028b88774abf', 'loadClassLoader'), true /*, true */);
23
  self::$loader = $loader = new xrstf_Composer52_ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInit077a9de49a58a2d7a901028b88774abf', '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 ComposerStaticInit4dd7b8af9819cda305271fc30af4e92e
8
  {
9
  public static $files = array (
10
  'b45b351e6b6f7487d819961fef2fda77' => __DIR__ . '/..' . '/jakeasmith/http_build_url/src/http_build_url.php',
@@ -42,6 +42,7 @@ class ComposerStaticInit4dd7b8af9819cda305271fc30af4e92e
42
  );
43
 
44
  public static $classMap = array (
 
45
  'WCML_Accommodation_Bookings' => __DIR__ . '/../..' . '/compatibility/class-wcml-accommodation-bookings.php',
46
  'WCML_Admin_Cookie' => __DIR__ . '/../..' . '/classes/class-wcml-admin-cookie.php',
47
  'WCML_Admin_Currency_Selector' => __DIR__ . '/../..' . '/classes/currencies/class-wcml-admin-currency-selector.php',
@@ -209,7 +210,7 @@ class ComposerStaticInit4dd7b8af9819cda305271fc30af4e92e
209
  'WCML_Upgrade' => __DIR__ . '/../..' . '/inc/class-wcml-upgrade.php',
210
  'WCML_Url_Filters_Redirect_Location' => __DIR__ . '/../..' . '/classes/url-filters/class-wcml-url-filters-redirect-location.php',
211
  'WCML_Url_Translation' => __DIR__ . '/../..' . '/inc/class-wcml-url-translation.php',
212
- 'WCML_Variation_Swatches_and_Photos' => __DIR__ . '/../..' . '/compatibility/class-wcml-variation-swatches-and-photos.php',
213
  'WCML_Vpc' => __DIR__ . '/../..' . '/compatibility/class-wcml-vpc.php',
214
  'WCML_W3TC_Multi_Currency' => __DIR__ . '/../..' . '/inc/currencies/class-wcml-w3tc-multi-currency.php',
215
  'WCML_WC_Admin_Duplicate_Product' => __DIR__ . '/../..' . '/inc/translation-editor/class-wcml-wc-admin-duplicate-product.php',
@@ -228,20 +229,23 @@ class ComposerStaticInit4dd7b8af9819cda305271fc30af4e92e
228
  'WCML_Woo_Var_Table' => __DIR__ . '/../..' . '/compatibility/class-wcml-woo-var-table.php',
229
  'WCML_WpFastest_Cache' => __DIR__ . '/../..' . '/compatibility/class-wcml-wpfastest-cache.php',
230
  'WCML_Wpb_Vc' => __DIR__ . '/../..' . '/compatibility/class-wcml-wpb-vc.php',
 
231
  'WCML_YITH_WCQV' => __DIR__ . '/../..' . '/compatibility/class-wcml-yith-wcqv.php',
232
  'WCML_gravityforms' => __DIR__ . '/../..' . '/compatibility/class-wcml-gravityforms.php',
233
  'WCML_wcExporter' => __DIR__ . '/../..' . '/compatibility/class-wcml-wcexporter.php',
234
  'WCML_xDomain_Data' => __DIR__ . '/../..' . '/classes/urls/class-wcml-xdomain-data.php',
 
 
235
  'woocommerce_wpml' => __DIR__ . '/../..' . '/classes/class-woocommerce-wpml.php',
236
  );
237
 
238
  public static function getInitializer(ClassLoader $loader)
239
  {
240
  return \Closure::bind(function () use ($loader) {
241
- $loader->prefixLengthsPsr4 = ComposerStaticInit4dd7b8af9819cda305271fc30af4e92e::$prefixLengthsPsr4;
242
- $loader->prefixDirsPsr4 = ComposerStaticInit4dd7b8af9819cda305271fc30af4e92e::$prefixDirsPsr4;
243
- $loader->prefixesPsr0 = ComposerStaticInit4dd7b8af9819cda305271fc30af4e92e::$prefixesPsr0;
244
- $loader->classMap = ComposerStaticInit4dd7b8af9819cda305271fc30af4e92e::$classMap;
245
 
246
  }, null, ClassLoader::class);
247
  }
4
 
5
  namespace Composer\Autoload;
6
 
7
+ class ComposerStaticInitdd99bdc714d3a0da336f7270f9054514
8
  {
9
  public static $files = array (
10
  'b45b351e6b6f7487d819961fef2fda77' => __DIR__ . '/..' . '/jakeasmith/http_build_url/src/http_build_url.php',
42
  );
43
 
44
  public static $classMap = array (
45
+ 'WCML_ATE_Activate_Synchronization' => __DIR__ . '/../..' . '/classes/ate/class-wcml-ate-activate-synchronization.php',
46
  'WCML_Accommodation_Bookings' => __DIR__ . '/../..' . '/compatibility/class-wcml-accommodation-bookings.php',
47
  'WCML_Admin_Cookie' => __DIR__ . '/../..' . '/classes/class-wcml-admin-cookie.php',
48
  'WCML_Admin_Currency_Selector' => __DIR__ . '/../..' . '/classes/currencies/class-wcml-admin-currency-selector.php',
210
  'WCML_Upgrade' => __DIR__ . '/../..' . '/inc/class-wcml-upgrade.php',
211
  'WCML_Url_Filters_Redirect_Location' => __DIR__ . '/../..' . '/classes/url-filters/class-wcml-url-filters-redirect-location.php',
212
  'WCML_Url_Translation' => __DIR__ . '/../..' . '/inc/class-wcml-url-translation.php',
213
+ 'WCML_Variation_Swatches_And_Photos' => __DIR__ . '/../..' . '/compatibility/class-wcml-variation-swatches-and-photos.php',
214
  'WCML_Vpc' => __DIR__ . '/../..' . '/compatibility/class-wcml-vpc.php',
215
  'WCML_W3TC_Multi_Currency' => __DIR__ . '/../..' . '/inc/currencies/class-wcml-w3tc-multi-currency.php',
216
  'WCML_WC_Admin_Duplicate_Product' => __DIR__ . '/../..' . '/inc/translation-editor/class-wcml-wc-admin-duplicate-product.php',
229
  'WCML_Woo_Var_Table' => __DIR__ . '/../..' . '/compatibility/class-wcml-woo-var-table.php',
230
  'WCML_WpFastest_Cache' => __DIR__ . '/../..' . '/compatibility/class-wcml-wpfastest-cache.php',
231
  'WCML_Wpb_Vc' => __DIR__ . '/../..' . '/compatibility/class-wcml-wpb-vc.php',
232
+ 'WCML_YIKES_Custom_Product_Tabs_Pro' => __DIR__ . '/../..' . '/compatibility/class-wcml-yikes-custom-product-tabs-pro.php',
233
  'WCML_YITH_WCQV' => __DIR__ . '/../..' . '/compatibility/class-wcml-yith-wcqv.php',
234
  'WCML_gravityforms' => __DIR__ . '/../..' . '/compatibility/class-wcml-gravityforms.php',
235
  'WCML_wcExporter' => __DIR__ . '/../..' . '/compatibility/class-wcml-wcexporter.php',
236
  'WCML_xDomain_Data' => __DIR__ . '/../..' . '/classes/urls/class-wcml-xdomain-data.php',
237
+ 'WPML_Core_Version_Check' => __DIR__ . '/..' . '/wpml-shared/wpml-lib-dependencies/src/dependencies/class-wpml-core-version-check.php',
238
+ 'WPML_Dependencies' => __DIR__ . '/..' . '/wpml-shared/wpml-lib-dependencies/src/dependencies/class-wpml-dependencies.php',
239
  'woocommerce_wpml' => __DIR__ . '/../..' . '/classes/class-woocommerce-wpml.php',
240
  );
241
 
242
  public static function getInitializer(ClassLoader $loader)
243
  {
244
  return \Closure::bind(function () use ($loader) {
245
+ $loader->prefixLengthsPsr4 = ComposerStaticInitdd99bdc714d3a0da336f7270f9054514::$prefixLengthsPsr4;
246
+ $loader->prefixDirsPsr4 = ComposerStaticInitdd99bdc714d3a0da336f7270f9054514::$prefixDirsPsr4;
247
+ $loader->prefixesPsr0 = ComposerStaticInitdd99bdc714d3a0da336f7270f9054514::$prefixesPsr0;
248
+ $loader->classMap = ComposerStaticInitdd99bdc714d3a0da336f7270f9054514::$classMap;
249
 
250
  }, null, ClassLoader::class);
251
  }
vendor/wpml-shared/wpml-lib-dependencies/src/dependencies/class-wpml-core-version-check.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WPML_Core_Version_Check {
4
+
5
+ public static function is_ok( $package_file_path ) {
6
+
7
+ $is_ok = false;
8
+
9
+ /** @var array $bundle */
10
+ $bundle = json_decode( file_get_contents( $package_file_path ), true );
11
+ if ( defined( 'ICL_SITEPRESS_VERSION' ) && is_array( $bundle ) ) {
12
+ $core_version_stripped = ICL_SITEPRESS_VERSION;
13
+ $dev_or_beta_pos = strpos( ICL_SITEPRESS_VERSION, '-' );
14
+ if ( $dev_or_beta_pos > 0 ) {
15
+ $core_version_stripped = substr( ICL_SITEPRESS_VERSION, 0, $dev_or_beta_pos );
16
+ }
17
+ if ( version_compare( $core_version_stripped, $bundle['sitepress-multilingual-cms'], '>=' ) ) {
18
+ $is_ok = true;
19
+ }
20
+ }
21
+
22
+ return $is_ok;
23
+ }
24
+ }
vendor/wpml-shared/wpml-lib-dependencies/src/dependencies/class-wpml-dependencies.php ADDED
@@ -0,0 +1,348 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ Module Name: WPML Dependency Check Module
4
+ Description: This is not a plugin! This module must be included in other plugins (WPML and add-ons) to handle compatibility checks
5
+ Author: OnTheGoSystems
6
+ Author URI: http://www.onthegosystems.com/
7
+ Version: 2.1
8
+ */
9
+
10
+ /** @noinspection PhpUndefinedClassInspection */
11
+ class WPML_Dependencies {
12
+ private static $instance;
13
+ private $admin_notice;
14
+ private $current_product;
15
+ private $current_version = array();
16
+ private $expected_versions = array();
17
+ private $installed_plugins = array();
18
+ private $invalid_plugins = array();
19
+ private $valid_plugins = array();
20
+ private $validation_results = array();
21
+
22
+ public $data_key = 'wpml_dependencies:';
23
+ public $needs_validation_key = 'wpml_dependencies:needs_validation';
24
+
25
+ private function __construct() {
26
+ if ( null === self::$instance ) {
27
+ $this->remove_old_admin_notices();
28
+ $this->init_hooks();
29
+ }
30
+ }
31
+
32
+ private function collect_data() {
33
+ $active_plugins = wp_get_active_and_valid_plugins();
34
+ $this->init_bundle( $active_plugins );
35
+ foreach ( $active_plugins as $plugin ) {
36
+ $this->add_installed_plugin( $plugin );
37
+ }
38
+ }
39
+
40
+ private function remove_old_admin_notices() {
41
+ if ( class_exists( 'WPML_Bundle_Check' ) ) {
42
+ global $WPML_Bundle_Check;
43
+
44
+ remove_action( 'admin_notices', array( $WPML_Bundle_Check, 'admin_notices_action' ) );
45
+ }
46
+ }
47
+
48
+ private function init_hooks() {
49
+ add_action( 'init', array( $this, 'init_plugins_action' ) );
50
+ add_action( 'extra_plugin_headers', array( $this, 'extra_plugin_headers_action' ) );
51
+ add_action( 'admin_notices', array( $this, 'admin_notices_action' ) );
52
+ add_action( 'activated_plugin', array( $this, 'activated_plugin_action' ) );
53
+ add_action( 'deactivated_plugin', array( $this, 'deactivated_plugin_action' ) );
54
+ add_action( 'upgrader_process_complete', array( $this, 'upgrader_process_complete_action' ), 10, 2 );
55
+ add_action( 'load-plugins.php', array( $this, 'run_validation_on_plugins_page' ) );
56
+ }
57
+
58
+ public function run_validation_on_plugins_page() {
59
+ $this->reset_validation();
60
+ }
61
+
62
+ public function activated_plugin_action() {
63
+ $this->reset_validation();
64
+ }
65
+
66
+ public function deactivated_plugin_action() {
67
+ $this->reset_validation();
68
+ }
69
+
70
+ public function upgrader_process_complete_action( $upgrader_object, $options ) {
71
+ if ( 'update' === $options['action'] && 'plugin' === $options['type'] ) {
72
+ $this->reset_validation();
73
+ }
74
+ }
75
+
76
+ private function reset_validation() {
77
+ update_option( $this->needs_validation_key, true );
78
+ $this->validate_plugins();
79
+ }
80
+
81
+ private function flag_as_validated() {
82
+ update_option( $this->needs_validation_key, false );
83
+ }
84
+
85
+ private function needs_validation() {
86
+ return get_option( $this->needs_validation_key );
87
+ }
88
+
89
+ public function admin_notices_action() {
90
+ $this->maybe_init_admin_notice();
91
+ if ( $this->admin_notice && ( is_admin() && ! $this->is_doing_ajax_cron_or_xmlrpc() ) ) {
92
+ echo $this->admin_notice;
93
+ }
94
+ }
95
+
96
+ private function is_doing_ajax_cron_or_xmlrpc() {
97
+ return ( $this->is_doing_ajax() || $this->is_doing_cron() || $this->is_doing_xmlrpc() );
98
+ }
99
+
100
+ private function is_doing_ajax() {
101
+ return ( defined( 'DOING_AJAX' ) && DOING_AJAX );
102
+ }
103
+
104
+ private function is_doing_cron() {
105
+ return ( defined( 'DOING_CRON' ) && DOING_CRON );
106
+ }
107
+
108
+ private function is_doing_xmlrpc() {
109
+ return ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST );
110
+ }
111
+
112
+ public function extra_plugin_headers_action( array $extra_headers = array() ) {
113
+ $new_extra_header = array(
114
+ 'PluginSlug' => 'Plugin Slug',
115
+ );
116
+
117
+ return array_merge( $new_extra_header, (array) $extra_headers );
118
+ }
119
+
120
+ /**
121
+ * @return WPML_Dependencies
122
+ */
123
+ public static function get_instance() {
124
+ if ( null === self::$instance ) {
125
+ self::$instance = new WPML_Dependencies();
126
+ }
127
+
128
+ return self::$instance;
129
+ }
130
+
131
+ public function get_plugins() {
132
+ return $this->installed_plugins;
133
+ }
134
+
135
+ public function init_plugins_action() {
136
+ if ( $this->needs_validation() && is_admin() && ! $this->is_doing_ajax_cron_or_xmlrpc() ) {
137
+ $this->init_plugins();
138
+ $this->validate_plugins();
139
+ $this->flag_as_validated();
140
+ }
141
+ }
142
+
143
+ private function init_plugins() {
144
+ if ( ! $this->installed_plugins ) {
145
+ if ( ! function_exists( 'get_plugin_data' ) ) {
146
+ /** @noinspection PhpIncludeInspection */
147
+ include_once ABSPATH . '/wp-admin/includes/plugin.php';
148
+ }
149
+ if ( function_exists( 'get_plugin_data' ) ) {
150
+ $this->collect_data();
151
+ }
152
+ }
153
+ update_option( $this->data_key . 'installed_plugins', $this->installed_plugins );
154
+ }
155
+
156
+ private function init_bundle( array $active_plugins ) {
157
+
158
+ foreach ( $active_plugins as $plugin_file ) {
159
+ $filename = dirname( $plugin_file ) . '/wpml-dependencies.json';
160
+ if ( file_exists( $filename ) ) {
161
+ $data = file_get_contents( $filename );
162
+ $bundle = json_decode( $data, true );
163
+ $this->set_expected_versions( $bundle );
164
+ }
165
+ }
166
+ }
167
+
168
+ private function add_installed_plugin( $plugin ) {
169
+ $data = get_plugin_data( $plugin );
170
+ $plugin_dir = dirname( $plugin );
171
+
172
+ if ( WP_PLUGIN_DIR . DIRECTORY_SEPARATOR !== $plugin_dir ) {
173
+ $plugin_folder = str_replace( WP_PLUGIN_DIR . DIRECTORY_SEPARATOR, '', $plugin_dir );
174
+ $plugin_slug = $this->guess_plugin_slug( $data, $plugin_folder );
175
+
176
+ if ( $this->is_valid_plugin( $plugin_slug ) ) {
177
+ $this->installed_plugins[ $plugin_slug ] = $data['Version'];
178
+ }
179
+ }
180
+ }
181
+
182
+ private function set_expected_versions( array $bundle ) {
183
+ foreach ( $bundle as $plugin => $version ) {
184
+ if ( ! array_key_exists( $plugin, $this->expected_versions ) ) {
185
+ $this->expected_versions[ $plugin ] = $version;
186
+ } else {
187
+ if ( version_compare( $this->expected_versions[ $plugin ], $version, '<' ) ) {
188
+ $this->expected_versions[ $plugin ] = $version;
189
+ }
190
+ }
191
+ }
192
+ }
193
+
194
+ private function guess_plugin_slug( $plugin_data, $plugin_folder ) {
195
+ $plugin_slug = null;
196
+ $plugin_slug = $plugin_folder;
197
+ if ( array_key_exists( 'Plugin Slug', $plugin_data ) && $plugin_data['Plugin Slug'] ) {
198
+ $plugin_slug = $plugin_data['Plugin Slug'];
199
+ }
200
+
201
+ return $plugin_slug;
202
+ }
203
+
204
+ private function validate_plugins() {
205
+ $validation_results = $this->get_plugins_validation();
206
+
207
+ $this->valid_plugins = array();
208
+ $this->invalid_plugins = array();
209
+ foreach ( $validation_results as $plugin => $validation_result ) {
210
+ if ( true === $validation_result ) {
211
+ $this->valid_plugins[] = $plugin;
212
+ } else {
213
+ $this->invalid_plugins[] = $plugin;
214
+ }
215
+ }
216
+
217
+ update_option( $this->data_key . 'valid_plugins', $this->valid_plugins );
218
+ update_option( $this->data_key . 'invalid_plugins', $this->invalid_plugins );
219
+ }
220
+
221
+ public function get_plugins_validation() {
222
+ foreach ( $this->installed_plugins as $plugin => $version ) {
223
+ $this->current_product = $plugin;
224
+ if ( $this->is_valid_plugin() ) {
225
+ $this->current_version = $version;
226
+ $validation_result = $this->is_plugin_version_valid();
227
+ $this->validation_results[ $plugin ] = $validation_result;
228
+ }
229
+ }
230
+
231
+ return $this->validation_results;
232
+ }
233
+
234
+ private function is_valid_plugin( $product = false ) {
235
+ $result = false;
236
+
237
+ if ( ! $product ) {
238
+ $product = $this->current_product;
239
+ }
240
+ if ( $product ) {
241
+ $versions = $this->get_expected_versions();
242
+ $result = array_key_exists( $product, $versions );
243
+ }
244
+
245
+ return $result;
246
+ }
247
+
248
+ public function is_plugin_version_valid() {
249
+ $expected_version = $this->filter_version( $this->get_expected_product_version() );
250
+
251
+ return $expected_version ? version_compare( $this->filter_version( $this->current_version ), $expected_version, '>=' ) : null;
252
+ }
253
+
254
+ private function filter_version( $version ) {
255
+ return preg_replace( '#[^\d.].*#', '', $version );
256
+ }
257
+
258
+ public function get_expected_versions() {
259
+ return $this->expected_versions;
260
+ }
261
+
262
+ private function get_expected_product_version( $product = false ) {
263
+ $result = null;
264
+
265
+ if ( ! $product ) {
266
+ $product = $this->current_product;
267
+ }
268
+ if ( $product ) {
269
+ $versions = $this->get_expected_versions();
270
+
271
+ $result = isset( $versions[ $product ] ) ? $versions[ $product ] : null;
272
+ }
273
+
274
+ return $result;
275
+ }
276
+
277
+ private function maybe_init_admin_notice() {
278
+ $this->admin_notice = null;
279
+ $this->installed_plugins = get_option( $this->data_key . 'installed_plugins', array() );
280
+ $this->invalid_plugins = get_option( $this->data_key . 'invalid_plugins', array() );
281
+ $this->valid_plugins = get_option( $this->data_key . 'valid_plugins', array() );
282
+
283
+ if ( $this->has_invalid_plugins() ) {
284
+ $notice_paragraphs = array();
285
+
286
+ $notice_paragraphs[] = $this->get_invalid_plugins_report_header();
287
+ $notice_paragraphs[] = $this->get_invalid_plugins_report_list();
288
+ $notice_paragraphs[] = $this->get_invalid_plugins_report_footer();
289
+
290
+ $this->admin_notice = '<div class="error wpml-admin-notice">';
291
+ $this->admin_notice .= '<h3>' . __( 'WPML Update is Incomplete', 'sitepress' ) . '</h3>';
292
+ $this->admin_notice .= '<p>' . implode( '</p><p>', $notice_paragraphs ) . '</p>';
293
+ $this->admin_notice .= '</div>';
294
+ }
295
+ }
296
+
297
+ public function has_invalid_plugins() {
298
+ return count( $this->invalid_plugins );
299
+ }
300
+
301
+ private function get_invalid_plugins_report_header() {
302
+ if ( $this->has_valid_plugins() ) {
303
+ if ( count( $this->valid_plugins ) === 1 ) {
304
+ $paragraph = __( 'You are running updated %s, but the following component is not updated:', 'sitepress' );
305
+ $paragraph = sprintf( $paragraph, '<strong>' . $this->valid_plugins[0] . '</strong>' );
306
+ } else {
307
+ $paragraph = __( 'You are running updated %s and %s, but the following components are not updated:', 'sitepress' );
308
+ $first_valid_plugins = implode( ', ', array_slice( $this->valid_plugins, 0, - 1 ) );
309
+ $last_valid_plugin = array_slice( $this->valid_plugins, - 1 );
310
+ $paragraph = sprintf( $paragraph, '<strong>' . $first_valid_plugins . '</strong>', '<strong>' . $last_valid_plugin[0] . '</strong>' );
311
+ }
312
+ } else {
313
+ $paragraph = __( 'The following components are not updated:', 'sitepress' );
314
+ }
315
+
316
+ return $paragraph;
317
+ }
318
+
319
+ private function get_invalid_plugins_report_list() {
320
+ $invalid_plugins_list = '<ul class="ul-disc">';
321
+ foreach ( $this->invalid_plugins as $invalid_plugin ) {
322
+ $plugin_name_html = '<li data-installed-version="' . $this->installed_plugins[ $invalid_plugin ] . '">';
323
+ $plugin_name_html .= $invalid_plugin;
324
+ $plugin_name_html .= '</li>';
325
+
326
+ $invalid_plugins_list .= $plugin_name_html;
327
+ }
328
+ $invalid_plugins_list .= '</ul>';
329
+
330
+ return $invalid_plugins_list;
331
+ }
332
+
333
+ private function get_invalid_plugins_report_footer() {
334
+ $wpml_org_url = '<a href="https://wpml.org/account/" title="WPML.org account">' . __( 'WPML.org account', 'sitepress' ) . '</a>';
335
+
336
+ $notice_paragraph = __( 'Your site will not work as it should in this configuration', 'sitepress' );
337
+ $notice_paragraph .= ' ';
338
+ $notice_paragraph .= __( 'Please update all components which you are using.', 'sitepress' );
339
+ $notice_paragraph .= ' ';
340
+ $notice_paragraph .= sprintf( __( 'For WPML components you can receive updates from your %s or automatically, after you register WPML.', 'sitepress' ), $wpml_org_url );
341
+
342
+ return $notice_paragraph;
343
+ }
344
+
345
+ private function has_valid_plugins() {
346
+ return $this->valid_plugins && count( $this->valid_plugins );
347
+ }
348
+ }
wpml-dependencies.json ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ {
2
+ "sitepress-multilingual-cms": "4.0.0",
3
+ "wpml-translation-management": "2.6.0",
4
+ "wpml-string-translation": "2.8.0",
5
+ "woocommerce-multilingual": "4.4.0"
6
+ }
wpml-woocommerce.php CHANGED
@@ -7,17 +7,17 @@
7
  Author URI: http://www.onthegosystems.com/
8
  Text Domain: woocommerce-multilingual
9
  Requires at least: 3.9
10
- Tested up to: 5.0.3
11
- Version: 4.4.2.1
12
  WC requires at least: 3.3.0
13
- WC tested up to: 3.5.4
14
  */
15
 
16
  if ( defined( 'WCML_VERSION' ) ) {
17
  return;
18
  }
19
 
20
- define( 'WCML_VERSION', '4.4.2.1' );
21
  define( 'WCML_PLUGIN_PATH', dirname( __FILE__ ) );
22
  define( 'WCML_PLUGIN_FOLDER', basename( WCML_PLUGIN_PATH ) );
23
  define( 'WCML_LOCALE_PATH', WCML_PLUGIN_PATH . '/locale' );
@@ -47,12 +47,14 @@ if ( defined( 'ICL_SITEPRESS_VERSION' ) && ! ICL_PLUGIN_INACTIVE && class_exists
47
  $wcml_cart_switch_lang_functions->add_actions();
48
  }
49
 
50
- // Load WooCommerce Multilingual when WPML is active
51
- global $woocommerce_wpml;
52
- $woocommerce_wpml = new woocommerce_wpml();
53
- $woocommerce_wpml->add_hooks();
 
 
 
54
 
55
- add_action( 'wpml_loaded', 'wcml_loader' );
56
  /**
57
  * Load WooCommerce Multilingual after WPML is loaded
58
  */
@@ -61,7 +63,8 @@ function wcml_loader(){
61
  $xdomain_data->add_hooks();
62
 
63
  $loaders = array(
64
- 'WCML_Privacy_Content_Factory'
 
65
  );
66
 
67
  if (
7
  Author URI: http://www.onthegosystems.com/
8
  Text Domain: woocommerce-multilingual
9
  Requires at least: 3.9
10
+ Tested up to: 5.1.1
11
+ Version: 4.5.0
12
  WC requires at least: 3.3.0
13
+ WC tested up to: 3.5.7
14
  */
15
 
16
  if ( defined( 'WCML_VERSION' ) ) {
17
  return;
18
  }
19
 
20
+ define( 'WCML_VERSION', '4.5.0' );
21
  define( 'WCML_PLUGIN_PATH', dirname( __FILE__ ) );
22
  define( 'WCML_PLUGIN_FOLDER', basename( WCML_PLUGIN_PATH ) );
23
  define( 'WCML_LOCALE_PATH', WCML_PLUGIN_PATH . '/locale' );
47
  $wcml_cart_switch_lang_functions->add_actions();
48
  }
49
 
50
+ if ( WPML_Core_Version_Check::is_ok( WCML_PLUGIN_PATH . '/wpml-dependencies.json' ) ) {
51
+ global $woocommerce_wpml;
52
+ $woocommerce_wpml = new woocommerce_wpml();
53
+ $woocommerce_wpml->add_hooks();
54
+
55
+ add_action( 'wpml_loaded', 'wcml_loader' );
56
+ }
57
 
 
58
  /**
59
  * Load WooCommerce Multilingual after WPML is loaded
60
  */
63
  $xdomain_data->add_hooks();
64
 
65
  $loaders = array(
66
+ 'WCML_Privacy_Content_Factory',
67
+ 'WCML_ATE_Activate_Synchronization',
68
  );
69
 
70
  if (