WooCommerce Multilingual – run WooCommerce with WPML - Version 4.0.0

Version Description

  • Added the option to configure automatic exchange rates for the multi-currency mode
  • Optimized the synchronization process between products and their translations when saving products
  • Added the option to reset the cart when switching the languages or currencies
  • Added compatibility updates for WordPress 4.7
  • Improved usability aspects related to popular compatible extensions
  • Added compatibility updates for upcoming WooCommerce 2.7
  • Fixed a compatibility issue with Yoast SEO premium: Redirects to the original product were created for translated variations
  • Fixed a compatibility issue with WooCommerce Tab Manager: HTML was stripped out when saving the translation of a tab
  • Bug fix: downloadable products were added multiple times to the cart (instead of quantity change)
  • Bug fix: order-pay endpoint string was re-registering itself with a blank value
Download this release

Release Info

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

Code changes from version 3.9.5 to 4.0.0

Files changed (129) hide show
  1. compatibility/class-wcml-bookings.php +43 -26
  2. compatibility/class-wcml-composite-products.php +1 -1
  3. compatibility/class-wcml-pip.php +1 -1
  4. compatibility/class-wcml-product-addons.php +21 -5
  5. compatibility/class-wcml-product-bundles.php +1 -1
  6. compatibility/class-wcml-tab-manager.php +14 -1
  7. compatibility/class-wcml-table-rate-shipping.php +31 -8
  8. compatibility/class-wcml-wc-subscriptions.php +15 -0
  9. compatibility/class-wcml-wpseo.php +16 -0
  10. inc/abstracts/class-wcml-exchange-rate-service.php +111 -0
  11. inc/admin-menus/class-wcml-setup.php +11 -1
  12. inc/class-wcml-cart-removed-items-widget.php +28 -0
  13. inc/class-wcml-cart.php +200 -43
  14. inc/class-wcml-emails.php +10 -1
  15. inc/class-wcml-endpoints.php +6 -3
  16. inc/class-wcml-orders.php +12 -8
  17. inc/class-wcml-products.php +10 -1
  18. inc/class-wcml-reports.php +11 -2
  19. inc/class-wcml-requests.php +18 -2
  20. inc/class-wcml-resources.php +16 -1
  21. inc/class-wcml-store-pages.php +5 -5
  22. inc/class-wcml-terms.php +1 -78
  23. inc/class-wcml-tp-support.php +10 -15
  24. inc/class-wcml-troubleshooting.php +2 -2
  25. inc/class-wcml-upgrade.php +8 -2
  26. inc/class-wcml-wc-gateways.php +101 -30
  27. inc/class-wcml-wc-strings.php +1 -1
  28. inc/class-wcml-widgets.php +26 -0
  29. inc/class-wcml-woocommerce-rest-api-support.php +4 -4
  30. inc/class-woocommerce-wpml.php +11 -4
  31. inc/constants.php +3 -0
  32. inc/currencies/class-wcml-admin-currency-selector.php +9 -7
  33. inc/currencies/class-wcml-currencies.php +0 -10
  34. inc/currencies/class-wcml-currency-switcher.php +1 -1
  35. inc/currencies/class-wcml-custom-prices.php +6 -1
  36. inc/currencies/class-wcml-exchange-rates.php +345 -0
  37. inc/currencies/class-wcml-multi-currency-configuration.php +19 -14
  38. inc/currencies/class-wcml-multi-currency-orders.php +2 -2
  39. inc/currencies/class-wcml-multi-currency.php +35 -6
  40. inc/currencies/exchange-rate-services/class-wcml-exchange-rates-currencylayer.php +75 -0
  41. inc/currencies/exchange-rate-services/class-wcml-exchange-rates-fixierio.php +60 -0
  42. inc/currencies/exchange-rate-services/class-wcml-exchange-rates-yahoo-finance.php +74 -0
  43. inc/deprecated-WC-functions.php +69 -0
  44. inc/template-classes/class-wcml-pointer-ui.php +49 -0
  45. inc/template-classes/class-wcml-products-ui.php +2 -2
  46. inc/template-classes/class-wcml-removed-cart-items-ui.php +86 -0
  47. inc/template-classes/class-wcml-settings-ui.php +27 -4
  48. inc/template-classes/multi-currency/class-wcml-currency-switcher-ui.php +2 -1
  49. inc/template-classes/multi-currency/class-wcml-custom-currency-options.php +17 -6
  50. inc/template-classes/multi-currency/class-wcml-exchange-rates-ui.php +92 -0
  51. inc/template-classes/multi-currency/class-wcml-multi-currency-ui.php +11 -7
  52. inc/template-classes/status/class-wcml-status-config-warnings-ui.php +0 -1
  53. inc/template-classes/status/class-wcml-status-taxonomies-ui.php +5 -5
  54. inc/translation-editor/class-wcml-editor-ui-product-job.php +66 -61
  55. inc/translation-editor/class-wcml-synchronize-product-data.php +648 -638
  56. inc/translation-editor/class-wcml-synchronize-variations-data.php +148 -145
  57. inc/wcml-cart-switch-lang-functions.php +66 -0
  58. locale/woocommerce-multilingual-ar.mo +0 -0
  59. locale/woocommerce-multilingual-de_DE.mo +0 -0
  60. locale/woocommerce-multilingual-el.mo +0 -0
  61. locale/woocommerce-multilingual-es_ES.mo +0 -0
  62. locale/woocommerce-multilingual-fr_FR.mo +0 -0
  63. locale/woocommerce-multilingual-he_IL.mo +0 -0
  64. locale/woocommerce-multilingual-it_IT.mo +0 -0
  65. locale/woocommerce-multilingual-ja.mo +0 -0
  66. locale/woocommerce-multilingual-ko_KR.mo +0 -0
  67. locale/woocommerce-multilingual-nl_NL.mo +0 -0
  68. locale/woocommerce-multilingual-pl_PL.mo +0 -0
  69. locale/woocommerce-multilingual-pt_BR.mo +0 -0
  70. locale/woocommerce-multilingual-pt_PT.mo +0 -0
  71. locale/woocommerce-multilingual-ru_RU.mo +0 -0
  72. locale/woocommerce-multilingual-sv_SE.mo +0 -0
  73. locale/woocommerce-multilingual-uk_UA.mo +0 -0
  74. locale/woocommerce-multilingual-vi.mo +0 -0
  75. locale/woocommerce-multilingual-zh_CN.mo +0 -0
  76. locale/woocommerce-multilingual-zh_TW.mo +0 -0
  77. readme.txt +13 -1
  78. res/css/admin.css +64 -1
  79. res/css/currency-switcher.css +1 -1
  80. res/css/management.css +1 -1
  81. res/js/cart_widget.min.js +1 -1
  82. res/js/dialogs.min.js +1 -1
  83. res/js/exchange-rates.js +101 -0
  84. res/js/front-scripts.js +20 -0
  85. res/js/front-scripts.min.js +1 -0
  86. res/js/jquery.cookie.min.js +1 -1
  87. res/js/languages_notice.min.js +1 -1
  88. res/js/lock_fields.min.js +1 -1
  89. res/js/multi-currency.js +12 -4
  90. res/js/multi-currency.min.js +1 -1
  91. res/js/pointer.js +69 -0
  92. res/js/pointer.min.js +1 -0
  93. res/js/scripts.js +0 -67
  94. res/js/scripts.min.js +1 -1
  95. res/js/troubleshooting.min.js +1 -1
  96. res/js/wcml-multi-currency.js +9 -3
  97. res/js/wcml-multi-currency.min.js +1 -1
  98. res/js/wcml-translation-editor.min.js +1 -1
  99. res/scss/admin.scss +49 -0
  100. res/scss/currency-switcher.scss +18 -0
  101. res/scss/management.scss +15 -12
  102. templates/multi-currency/currency-switcher-options.twig +4 -4
  103. templates/multi-currency/custom-currency-options.twig +5 -4
  104. templates/multi-currency/exchange-rates.twig +124 -0
  105. templates/multi-currency/multi-currency.twig +5 -1
  106. templates/pointer-ui.twig +19 -0
  107. templates/removed-cart-items.twig +14 -0
  108. templates/settings-ui.twig +50 -0
  109. templates/status/conf-warn.twig +0 -1
  110. templates/status/taxonomies.twig +3 -13
  111. vendor/autoload.php +2 -2
  112. vendor/autoload_52.php +1 -1
  113. vendor/composer/ClassLoader.php +10 -7
  114. vendor/composer/autoload_classmap.php +12 -0
  115. vendor/composer/autoload_real.php +4 -4
  116. vendor/composer/autoload_real_52.php +3 -3
  117. vendor/composer/autoload_static.php +17 -5
  118. vendor/composer/installed.json +4 -4
  119. vendor/composer/installers/5450262f6ba3420d0675f65877346e3e +0 -0
  120. vendor/otgs/installer/changelog.txt +4 -0
  121. vendor/otgs/installer/includes/class-installer-dependencies.php +2 -2
  122. vendor/otgs/installer/includes/class-installer-theme.php +6 -6
  123. vendor/otgs/installer/includes/installer.class.php +451 -433
  124. vendor/otgs/installer/installer.php +1 -1
  125. vendor/otgs/installer/loader.php +1 -1
  126. vendor/otgs/installer/res/js/admin.js +0 -1
  127. vendor/otgs/installer/templates/repository-listing.php +0 -1
  128. wpml-config.xml +1 -1
  129. wpml-woocommerce.php +8 -5
compatibility/class-wcml-bookings.php CHANGED
@@ -158,6 +158,8 @@ class WCML_Bookings {
158
 
159
  //allow filtering resources by language
160
  add_filter( 'get_booking_resources_args', array( $this, 'filter_get_booking_resources_args' ) );
 
 
161
  }
162
 
163
  if ( ! is_admin() || isset( $_POST['action'] ) && $_POST['action'] == 'wc_bookings_calculate_costs' ) {
@@ -172,7 +174,7 @@ class WCML_Bookings {
172
  ), 10, 4 );
173
  }
174
 
175
- add_filter( 'wpml_extra_conditions_snippet', array( $this, 'extra_conditions_to_filter_bookings' ) );
176
 
177
  $this->clear_transient_fields();
178
 
@@ -991,16 +993,20 @@ class WCML_Bookings {
991
  function load_assets( $external_product_type = false ) {
992
  global $pagenow;
993
 
994
- $product = $pagenow == 'post.php' && isset( $_GET['post'] ) ? wc_get_product( $_GET['post'] ) : false;
 
 
 
995
 
996
- if ( ( $product && ( $product->product_type == 'booking' || $product->product_type == $external_product_type ) ) || $pagenow == 'post-new.php' ) {
997
 
998
- wp_register_style( 'wcml-bookings-css', WCML_PLUGIN_URL . '/compatibility/res/css/wcml-bookings.css', array(), WCML_VERSION );
999
- wp_enqueue_style( 'wcml-bookings-css' );
1000
 
1001
- wp_register_script( 'wcml-bookings-js', WCML_PLUGIN_URL . '/compatibility/res/js/wcml-bookings.js', array( 'jquery' ), WCML_VERSION );
1002
- wp_enqueue_script( 'wcml-bookings-js' );
1003
 
 
1004
  }
1005
 
1006
  }
@@ -1021,8 +1027,8 @@ class WCML_Bookings {
1021
  if ( $cart_item['data'] instanceof WC_Product_Booking && isset( $cart_item['booking'] ) ) {
1022
 
1023
 
1024
- $current_id = apply_filters( 'translate_object_id', $cart_item['data']->id, 'product', true, $current_language );
1025
- $cart_product_id = $cart_item['data']->id;
1026
 
1027
  if ( $current_id != $cart_product_id ) {
1028
 
@@ -1221,7 +1227,7 @@ class WCML_Bookings {
1221
  }
1222
 
1223
  function custom_box_html( $obj, $product_id, $data ) {
1224
- if ( wc_get_product( $product_id )->product_type != 'booking' ) {
1225
  return;
1226
  }
1227
 
@@ -1284,7 +1290,7 @@ class WCML_Bookings {
1284
 
1285
  function custom_box_html_data( $data, $product_id, $translation, $lang ) {
1286
 
1287
- if ( wc_get_product( $product_id )->product_type != 'booking' ) {
1288
  return $data;
1289
  }
1290
 
@@ -1762,12 +1768,9 @@ class WCML_Bookings {
1762
  function append_persons_to_translation_package( $package, $post ) {
1763
 
1764
  if ( $post->post_type == 'product' ) {
1765
- $product = wc_get_product( $post->ID );
1766
-
1767
- //WC_Product::get_type() available from WooCommerce 2.4.0
1768
- $product_type = method_exists( $product, 'get_type' ) ? $product->get_type() : $product->product_type;
1769
 
1770
- if ( $product_type == 'booking' ) {
1771
 
1772
  $bookable_product = new WC_Product_Booking( $post->ID );
1773
 
@@ -1800,10 +1803,7 @@ class WCML_Bookings {
1800
  function save_person_translation( $post_id, $data, $job ) {
1801
  $person_translations = array();
1802
 
1803
- $product = wc_get_product( $post_id );
1804
-
1805
- if ( $product && $product->product_type == 'booking' ) {
1806
-
1807
 
1808
  foreach ( $data as $value ) {
1809
 
@@ -1870,10 +1870,9 @@ class WCML_Bookings {
1870
  if ( $post->post_type == 'product' ) {
1871
  $product = wc_get_product( $post->ID );
1872
 
1873
- //WC_Product::get_type() available from WooCommerce 2.4.0
1874
- $product_type = method_exists( $product, 'get_type' ) ? $product->get_type() : $product->product_type;
1875
 
1876
- if ( $product_type == 'booking' && $product->has_resources() ) {
1877
 
1878
  $resources = $product->get_resources();
1879
 
@@ -1898,9 +1897,7 @@ class WCML_Bookings {
1898
  function save_resource_translation( $post_id, $data, $job ) {
1899
  $resource_translations = array();
1900
 
1901
- $product = wc_get_product( $post_id );
1902
-
1903
- if ( $product && $product->product_type == 'booking' ) {
1904
 
1905
  foreach ( $data as $value ) {
1906
 
@@ -2232,4 +2229,24 @@ class WCML_Bookings {
2232
  return $types;
2233
  }
2234
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2235
  }
158
 
159
  //allow filtering resources by language
160
  add_filter( 'get_booking_resources_args', array( $this, 'filter_get_booking_resources_args' ) );
161
+
162
+ add_action( 'woocommerce_product_data_panels', array( $this, 'show_pointer_info' ) );
163
  }
164
 
165
  if ( ! is_admin() || isset( $_POST['action'] ) && $_POST['action'] == 'wc_bookings_calculate_costs' ) {
174
  ), 10, 4 );
175
  }
176
 
177
+ add_filter( 'wpml_language_filter_extra_conditions_snippet', array( $this, 'extra_conditions_to_filter_bookings' ) );
178
 
179
  $this->clear_transient_fields();
180
 
993
  function load_assets( $external_product_type = false ) {
994
  global $pagenow;
995
 
996
+ $product_id = $pagenow == 'post.php' && isset( $_GET['post'] ) ? (int)$_GET['post'] : false;
997
+
998
+ if( $product_id && get_post_type( $product_id ) === 'product' ){
999
+ $product_type = Deprecated_WC_Functions::get_product_type( $product_id );
1000
 
1001
+ if ( ( $product_type === 'booking' || $product_type === $external_product_type ) || $pagenow == 'post-new.php' ) {
1002
 
1003
+ wp_register_style( 'wcml-bookings-css', WCML_PLUGIN_URL . '/compatibility/res/css/wcml-bookings.css', array(), WCML_VERSION );
1004
+ wp_enqueue_style( 'wcml-bookings-css' );
1005
 
1006
+ wp_register_script( 'wcml-bookings-js', WCML_PLUGIN_URL . '/compatibility/res/js/wcml-bookings.js', array( 'jquery' ), WCML_VERSION );
1007
+ wp_enqueue_script( 'wcml-bookings-js' );
1008
 
1009
+ }
1010
  }
1011
 
1012
  }
1027
  if ( $cart_item['data'] instanceof WC_Product_Booking && isset( $cart_item['booking'] ) ) {
1028
 
1029
 
1030
+ $current_id = apply_filters( 'translate_object_id', $cart_item['product_id'], 'product', true, $current_language );
1031
+ $cart_product_id = $cart_item['product_id'];
1032
 
1033
  if ( $current_id != $cart_product_id ) {
1034
 
1227
  }
1228
 
1229
  function custom_box_html( $obj, $product_id, $data ) {
1230
+ if ( Deprecated_WC_Functions::get_product_type( $product_id ) !== 'booking' ) {
1231
  return;
1232
  }
1233
 
1290
 
1291
  function custom_box_html_data( $data, $product_id, $translation, $lang ) {
1292
 
1293
+ if ( Deprecated_WC_Functions::get_product_type( $product_id ) !== 'booking' ) {
1294
  return $data;
1295
  }
1296
 
1768
  function append_persons_to_translation_package( $package, $post ) {
1769
 
1770
  if ( $post->post_type == 'product' ) {
1771
+ $product_type = Deprecated_WC_Functions::get_product_type( $post->ID );
 
 
 
1772
 
1773
+ if ( $product_type === 'booking' ) {
1774
 
1775
  $bookable_product = new WC_Product_Booking( $post->ID );
1776
 
1803
  function save_person_translation( $post_id, $data, $job ) {
1804
  $person_translations = array();
1805
 
1806
+ if ( Deprecated_WC_Functions::get_product_type( $post_id ) === 'booking' ) {
 
 
 
1807
 
1808
  foreach ( $data as $value ) {
1809
 
1870
  if ( $post->post_type == 'product' ) {
1871
  $product = wc_get_product( $post->ID );
1872
 
1873
+ $product_type = Deprecated_WC_Functions::get_product_type( $post->ID );
 
1874
 
1875
+ if ( $product_type === 'booking' && $product->has_resources() ) {
1876
 
1877
  $resources = $product->get_resources();
1878
 
1897
  function save_resource_translation( $post_id, $data, $job ) {
1898
  $resource_translations = array();
1899
 
1900
+ if ( Deprecated_WC_Functions::get_product_type( $post_id ) === 'booking' ) {
 
 
1901
 
1902
  foreach ( $data as $value ) {
1903
 
2229
  return $types;
2230
  }
2231
 
2232
+ public function show_pointer_info(){
2233
+
2234
+ $pointer_ui = new WCML_Pointer_UI(
2235
+ sprintf( __( 'You can translate the titles of your custom Resources on the %sWooCommerce product translation page%s', 'woocommerce-multilingual' ), '<a href="'.admin_url('admin.php?page=wpml-wcml').'">', '</a>' ),
2236
+ 'https://wpml.org/documentation/woocommerce-extensions-compatibility/translating-woocommerce-bookings-woocommerce-multilingual/',
2237
+ 'bookings_resources .woocommerce_bookable_resources #message'
2238
+ );
2239
+
2240
+ $pointer_ui->show();
2241
+
2242
+ $pointer_ui = new WCML_Pointer_UI(
2243
+ sprintf( __( 'You can translate the Person Type Name and Description on the %sWooCommerce product translation page%s', 'woocommerce-multilingual' ), '<a href="'.admin_url('admin.php?page=wpml-wcml').'">', '</a>' ),
2244
+ 'https://wpml.org/documentation/woocommerce-extensions-compatibility/translating-woocommerce-bookings-woocommerce-multilingual/',
2245
+ 'bookings_persons #persons-types>div.toolbar'
2246
+ );
2247
+
2248
+ $pointer_ui->show();
2249
+
2250
+ }
2251
+
2252
  }
compatibility/class-wcml-composite-products.php CHANGED
@@ -448,7 +448,7 @@ class WCML_Composite_Products extends WCML_Compatibility_Helper{
448
  function load_assets( ){
449
  global $pagenow;
450
 
451
- if( ( $pagenow == 'post.php' && isset( $_GET[ 'post' ] ) && wc_get_product( $_GET[ 'post' ] )->product_type == 'composite' ) || $pagenow == 'post-new.php' ){
452
  wp_register_script( 'wcml-composite-js', WCML_PLUGIN_URL . '/compatibility/res/js/wcml-composite.js', array( 'jquery' ), WCML_VERSION );
453
  wp_enqueue_script( 'wcml-composite-js' );
454
 
448
  function load_assets( ){
449
  global $pagenow;
450
 
451
+ if( ( $pagenow == 'post.php' && isset( $_GET[ 'post' ] ) && Deprecated_WC_Functions::get_product_type( $_GET[ 'post' ] ) === 'composite' ) || $pagenow == 'post-new.php' ){
452
  wp_register_script( 'wcml-composite-js', WCML_PLUGIN_URL . '/compatibility/res/js/wcml-composite.js', array( 'jquery' ), WCML_VERSION );
453
  wp_enqueue_script( 'wcml-composite-js' );
454
 
compatibility/class-wcml-pip.php CHANGED
@@ -77,7 +77,7 @@ class WCML_Pip{
77
 
78
  $the_order = new WC_Order( $pip_order_id );
79
  if( $the_order ){
80
- $currency = method_exists( $the_order, 'get_currency' ) ? $the_order->get_currency() : ( method_exists( $the_order, 'get_order_currency' ) ? $the_order->get_order_currency() : '' ) ;
81
 
82
  if( !$currency && isset( $_COOKIE[ '_wcml_order_currency' ] ) ){
83
  $currency = $_COOKIE[ '_wcml_order_currency' ];
77
 
78
  $the_order = new WC_Order( $pip_order_id );
79
  if( $the_order ){
80
+ $currency = Deprecated_WC_Functions::get_order_currency( $the_order );
81
 
82
  if( !$currency && isset( $_COOKIE[ '_wcml_order_currency' ] ) ){
83
  $currency = $_COOKIE[ '_wcml_order_currency' ];
compatibility/class-wcml-product-addons.php CHANGED
@@ -33,13 +33,15 @@ class WCML_Product_Addons {
33
  add_action( 'admin_notices', array( $this, 'inf_translate_strings' ) );
34
  }
35
 
36
- add_action( 'addons_panel_start', array( $this, 'inf_translate_strings' ) );
37
 
38
  if ( is_admin() ) {
39
 
40
  add_action( 'wcml_gui_additional_box_html', array( $this, 'custom_box_html' ), 10, 3 );
41
  add_filter( 'wcml_gui_additional_box_data', array( $this, 'custom_box_html_data' ), 10, 3 );
42
  add_action( 'wcml_update_extra_fields', array( $this, 'addons_update' ), 10, 3 );
 
 
43
  }
44
  }
45
 
@@ -132,11 +134,14 @@ class WCML_Product_Addons {
132
  }
133
 
134
  function inf_translate_strings() {
135
- $message = '<div><p class="icl_cyan_box">';
136
- $message .= sprintf( __( 'To translate Add-ons strings please save Add-ons and go to the <b><a href="%s">String Translation interface</a></b>', 'woocommerce-multilingual' ), admin_url( 'admin.php?page='.WPML_ST_FOLDER.'/menu/string-translation.php&context=wc_product_addons_strings' ) );
137
- $message .= '</p></div>';
138
 
139
- echo $message;
 
 
 
 
 
 
140
  }
141
 
142
  /**
@@ -244,4 +249,15 @@ class WCML_Product_Addons {
244
 
245
  update_post_meta( $product_id, '_product_addons', $product_addons );
246
  }
 
 
 
 
 
 
 
 
 
 
 
247
  }
33
  add_action( 'admin_notices', array( $this, 'inf_translate_strings' ) );
34
  }
35
 
36
+ add_action( 'woocommerce-product-addons_panel_start', array( $this, 'show_pointer_info' ) );
37
 
38
  if ( is_admin() ) {
39
 
40
  add_action( 'wcml_gui_additional_box_html', array( $this, 'custom_box_html' ), 10, 3 );
41
  add_filter( 'wcml_gui_additional_box_data', array( $this, 'custom_box_html_data' ), 10, 3 );
42
  add_action( 'wcml_update_extra_fields', array( $this, 'addons_update' ), 10, 3 );
43
+
44
+ add_action( 'woocommerce_product_data_panels', array( $this, 'show_pointer_info' ) );
45
  }
46
  }
47
 
134
  }
135
 
136
  function inf_translate_strings() {
 
 
 
137
 
138
+ $pointer_ui = new WCML_Pointer_UI(
139
+ sprintf( __( 'You can translate strings related to global add-ons on the %sWPML String Translation page%s. Use the search on the top of that page to find the strings.', 'woocommerce-multilingual' ), '<a href="'.admin_url('admin.php?page='.WPML_ST_FOLDER.'/menu/string-translation.php&context=wc_product_addons_strings').'">', '</a>' ),
140
+ 'https://wpml.org/documentation/woocommerce-extensions-compatibility/translating-woocommerce-product-add-ons-woocommerce-multilingual/',
141
+ 'wpbody-content .woocommerce h2'
142
+ );
143
+
144
+ $pointer_ui->show();
145
  }
146
 
147
  /**
249
 
250
  update_post_meta( $product_id, '_product_addons', $product_addons );
251
  }
252
+
253
+ public function show_pointer_info(){
254
+
255
+ $pointer_ui = new WCML_Pointer_UI(
256
+ sprintf( __( 'You can translate the Group Name, Group Description and every Option Label of your product add-on on the %sWooCommerce product translation page%s', 'woocommerce-multilingual' ), '<a href="'.admin_url('admin.php?page=wpml-wcml').'">', '</a>' ),
257
+ 'https://wpml.org/documentation/woocommerce-extensions-compatibility/translating-woocommerce-product-add-ons-woocommerce-multilingual/',
258
+ 'product_addons_data>p'
259
+ );
260
+
261
+ $pointer_ui->show();
262
+ }
263
  }
compatibility/class-wcml-product-bundles.php CHANGED
@@ -327,7 +327,7 @@ class WCML_Product_Bundles{
327
 
328
  function resync_bundle_clean( $cart ) {
329
  foreach ( $cart->cart_contents as $cart_item_key => $cart_item ) {
330
- if ( isset( $cart_item[ 'bundled_items' ] ) && $cart_item[ 'data' ]->product_type === 'bundle' ) {
331
  if ( isset( $cart_item[ 'remapped_bundled_item_ids' ] ) ) {
332
  unset( WC()->cart->cart_contents[ $cart_item_key ][ 'remapped_bundled_item_ids' ] );
333
  }
327
 
328
  function resync_bundle_clean( $cart ) {
329
  foreach ( $cart->cart_contents as $cart_item_key => $cart_item ) {
330
+ if ( isset( $cart_item[ 'bundled_items' ] ) && Deprecated_WC_Functions::get_product_type( $cart_item[ 'product_id' ] ) === 'bundle' ) {
331
  if ( isset( $cart_item[ 'remapped_bundled_item_ids' ] ) ) {
332
  unset( WC()->cart->cart_contents[ $cart_item_key ][ 'remapped_bundled_item_ids' ] );
333
  }
compatibility/class-wcml-tab-manager.php CHANGED
@@ -63,6 +63,7 @@ class WCML_Tab_Manager {
63
 
64
  add_filter( 'wpml_tm_translation_job_data', array( $this, 'append_custom_tabs_to_translation_package' ), 10, 2 );
65
  add_action( 'wpml_translation_job_saved', array( $this, 'save_custom_tabs_translation' ), 10, 3 );
 
66
 
67
  }else{
68
  add_filter( 'option_wc_tab_manager_default_layout', array( $this, 'filter_default_layout' ) );
@@ -144,7 +145,7 @@ class WCML_Tab_Manager {
144
  $title_key = md5( 'tab_' . $orig_prod_tab['position'] . '_title' );
145
  $heading_key = md5( 'tab_' . $orig_prod_tab['position'] . '_heading' );
146
  $title = isset( $data[ $title_key ] ) ? sanitize_text_field( $data[ $title_key ] ) : '';
147
- $content = isset( $data[ $heading_key ] ) ? sanitize_text_field( $data[ $heading_key ] ) : '';
148
 
149
  $trnsl_product_tabs = $this->set_product_tab( $orig_prod_tab, $trnsl_product_tabs, $lang, $trnsl_product_id, $tab_id, $title, $content );
150
 
@@ -704,4 +705,16 @@ class WCML_Tab_Manager {
704
 
705
  return $default_tabs;
706
  }
 
 
 
 
 
 
 
 
 
 
 
 
707
  }
63
 
64
  add_filter( 'wpml_tm_translation_job_data', array( $this, 'append_custom_tabs_to_translation_package' ), 10, 2 );
65
  add_action( 'wpml_translation_job_saved', array( $this, 'save_custom_tabs_translation' ), 10, 3 );
66
+ add_action( 'woocommerce_product_data_panels', array( $this, 'show_pointer_info' ) );
67
 
68
  }else{
69
  add_filter( 'option_wc_tab_manager_default_layout', array( $this, 'filter_default_layout' ) );
145
  $title_key = md5( 'tab_' . $orig_prod_tab['position'] . '_title' );
146
  $heading_key = md5( 'tab_' . $orig_prod_tab['position'] . '_heading' );
147
  $title = isset( $data[ $title_key ] ) ? sanitize_text_field( $data[ $title_key ] ) : '';
148
+ $content = isset( $data[ $heading_key ] ) ? wp_kses_post( $data[ $heading_key ] ) : '';
149
 
150
  $trnsl_product_tabs = $this->set_product_tab( $orig_prod_tab, $trnsl_product_tabs, $lang, $trnsl_product_id, $tab_id, $title, $content );
151
 
705
 
706
  return $default_tabs;
707
  }
708
+
709
+ public function show_pointer_info(){
710
+
711
+ $pointer_ui = new WCML_Pointer_UI(
712
+ sprintf( __( 'You can translate your custom product tabs on the %sWooCommerce product translation page%s', 'woocommerce-multilingual' ), '<a href="'.admin_url('admin.php?page=wpml-wcml').'">', '</a>' ),
713
+ 'https://wpml.org/documentation/woocommerce-extensions-compatibility/translating-woocommerce-tab-manager-woocommerce-multilingual/',
714
+ 'woocommerce_product_tabs>p'
715
+ );
716
+
717
+ $pointer_ui->show();
718
+
719
+ }
720
  }
compatibility/class-wcml-table-rate-shipping.php CHANGED
@@ -49,16 +49,19 @@ class WCML_Table_Rate_Shipping {
49
  isset( $_GET[ 'tab' ] ) &&
50
  $_GET['tab'] == 'shipping'
51
  )
52
- ) &&
53
- isset( $_POST[ 'shipping_label' ] ) &&
54
- isset( $_POST[ 'woocommerce_table_rate_title' ] )
55
  ) {
56
 
57
- do_action( 'wpml_register_single_string', 'woocommerce', sanitize_text_field( $_POST[ 'woocommerce_table_rate_title' ] ) . '_shipping_method_title', sanitize_text_field( $_POST[ 'woocommerce_table_rate_title' ] ) );
58
- $shipping_labels = array_map( 'woocommerce_clean', $_POST[ 'shipping_label' ] );
59
- foreach ( $shipping_labels as $key => $shipping_label ) {
60
- $rate_key = isset( $_GET[ 'instance_id' ] ) ? 'table_rate'.$_GET[ 'instance_id' ].$_POST[ 'rate_id' ][ $key ] : $shipping_label;
61
- do_action( 'wpml_register_single_string', 'woocommerce', $rate_key. '_shipping_method_title', $shipping_label );
 
 
 
 
 
62
  }
63
  }
64
  }
@@ -102,6 +105,26 @@ class WCML_Table_Rate_Shipping {
102
  return $args;
103
  }
104
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
 
106
  public function filter_product_base_price( $row_base_price, $_product, $qty ){
107
 
49
  isset( $_GET[ 'tab' ] ) &&
50
  $_GET['tab'] == 'shipping'
51
  )
52
+ )
 
 
53
  ) {
54
 
55
+ $this->show_pointer_info();
56
+
57
+ if( isset( $_POST[ 'shipping_label' ] ) &&
58
+ isset( $_POST[ 'woocommerce_table_rate_title' ] ) ){
59
+ do_action( 'wpml_register_single_string', 'woocommerce', sanitize_text_field( $_POST[ 'woocommerce_table_rate_title' ] ) . '_shipping_method_title', sanitize_text_field( $_POST[ 'woocommerce_table_rate_title' ] ) );
60
+ $shipping_labels = array_map( 'woocommerce_clean', $_POST[ 'shipping_label' ] );
61
+ foreach ( $shipping_labels as $key => $shipping_label ) {
62
+ $rate_key = isset( $_GET[ 'instance_id' ] ) ? 'table_rate'.$_GET[ 'instance_id' ].$_POST[ 'rate_id' ][ $key ] : $shipping_label;
63
+ do_action( 'wpml_register_single_string', 'woocommerce', $rate_key. '_shipping_method_title', $shipping_label );
64
+ }
65
  }
66
  }
67
  }
105
  return $args;
106
  }
107
 
108
+ public function show_pointer_info(){
109
+
110
+ $pointer_ui = new WCML_Pointer_UI(
111
+ sprintf( __( 'You can translate this method title on the %sWPML String Translation page%s. Use the search on the top of that page to find the method title string.', 'woocommerce-multilingual' ), '<a href="'.admin_url('admin.php?page='.WPML_ST_FOLDER.'/menu/string-translation.php').'">', '</a>' ),
112
+ 'https://wpml.org/documentation/woocommerce-extensions-compatibility/translating-woocommerce-table-rate-shipping-woocommerce-multilingual/',
113
+ 'woocommerce_table_rate_title'
114
+ );
115
+
116
+ $pointer_ui->show();
117
+
118
+
119
+ $pointer_ui = new WCML_Pointer_UI(
120
+ sprintf( __( 'You can translate the labels of your table rates on the %sWPML String Translation page%s. Use the search on the top of that page to find the labels strings.', 'woocommerce-multilingual' ), '<a href="'.admin_url('admin.php?page='.WPML_ST_FOLDER.'/menu/string-translation.php').'">', '</a>' ),
121
+ 'https://wpml.org/documentation/woocommerce-extensions-compatibility/translating-woocommerce-table-rate-shipping-woocommerce-multilingual/',
122
+ 'shipping_rates .shipping_label a'
123
+ );
124
+
125
+ $pointer_ui->show();
126
+ }
127
+
128
 
129
  public function filter_product_base_price( $row_base_price, $_product, $qty ){
130
 
compatibility/class-wcml-wc-subscriptions.php CHANGED
@@ -22,6 +22,9 @@ class WCML_WC_Subscriptions{
22
 
23
  // reenable coupons for subscriptions when multicurrency is on
24
  add_action('woocommerce_subscription_cart_after_grouping', array($this, 'woocommerce_subscription_cart_after_grouping'));
 
 
 
25
  }
26
 
27
  function init(){
@@ -182,4 +185,16 @@ class WCML_WC_Subscriptions{
182
 
183
  return $endpoint;
184
  }
 
 
 
 
 
 
 
 
 
 
 
 
185
  }
22
 
23
  // reenable coupons for subscriptions when multicurrency is on
24
  add_action('woocommerce_subscription_cart_after_grouping', array($this, 'woocommerce_subscription_cart_after_grouping'));
25
+
26
+ add_action( 'woocommerce_subscriptions_product_options_pricing', array( $this, 'show_pointer_info' ) );
27
+ add_action( 'woocommerce_variable_subscription_pricing', array( $this, 'show_pointer_info' ) );
28
  }
29
 
30
  function init(){
185
 
186
  return $endpoint;
187
  }
188
+
189
+ public function show_pointer_info(){
190
+
191
+ $pointer_ui = new WCML_Pointer_UI(
192
+ sprintf( __( 'You can translate strings related to subscription products on the %sWPML String Translation page%s. Use the search on the top of that page to find the strings.', 'woocommerce-multilingual' ), '<a href="'.admin_url('admin.php?page='.WPML_ST_FOLDER.'/menu/string-translation.php&context=woocommerce_subscriptions').'">', '</a>' ),
193
+ 'https://wpml.org/documentation/woocommerce-extensions-compatibility/translating-woocommerce-subscriptions-woocommerce-multilingual/',
194
+ 'general_product_data .subscription_pricing',
195
+ 'prepend'
196
+ );
197
+
198
+ $pointer_ui->show();
199
+ }
200
  }
compatibility/class-wcml-wpseo.php CHANGED
@@ -2,6 +2,8 @@
2
 
3
  class WCML_WPSEO{
4
 
 
 
5
  function __construct(){
6
 
7
  add_filter( 'wcml_product_content_label', array( $this, 'wpseo_custom_field_label' ), 10, 2 );
@@ -14,6 +16,8 @@ class WCML_WPSEO{
14
  }
15
  }
16
 
 
 
17
  }
18
 
19
  function wpseo_custom_field_label( $field, $product_id ){
@@ -36,6 +40,18 @@ class WCML_WPSEO{
36
  return $field;
37
  }
38
 
 
 
 
 
 
 
 
 
 
 
 
 
39
 
40
  }
41
 
2
 
3
  class WCML_WPSEO{
4
 
5
+ private $updated_post_id;
6
+
7
  function __construct(){
8
 
9
  add_filter( 'wcml_product_content_label', array( $this, 'wpseo_custom_field_label' ), 10, 2 );
16
  }
17
  }
18
 
19
+ add_action( 'post_updated', array( $this, 'set_updated_post_id' ) );
20
+ add_action( 'wpseo_premium_post_redirect_slug_change', array( $this, 'wpseo_premium_post_redirect_slug_change' ) );
21
  }
22
 
23
  function wpseo_custom_field_label( $field, $product_id ){
40
  return $field;
41
  }
42
 
43
+ function set_updated_post_id( $post_id ){
44
+ $this->updated_post_id = $post_id;
45
+ }
46
+
47
+ function wpseo_premium_post_redirect_slug_change( $slug_changed_flag ){
48
+
49
+ if( null !== $this->updated_post_id && get_post_type( $this->updated_post_id ) === 'product_variation' ){
50
+ return true;
51
+ }
52
+
53
+ return $slug_changed_flag;
54
+ }
55
 
56
  }
57
 
inc/abstracts/class-wcml-exchange-rate-service.php ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ abstract class WCML_Exchange_Rate_Service{
4
+
5
+ private $id;
6
+ private $name;
7
+ private $url;
8
+ private $api_url;
9
+
10
+ private $settings = array();
11
+
12
+ protected $api_key = '';
13
+
14
+ const REQUIRES_KEY = false;
15
+
16
+ public function __construct( $id, $name, $api_url, $url = '' ) {
17
+
18
+ $this->id = $id;
19
+ $this->name = $name;
20
+ $this->api_url = $api_url;
21
+ $this->url = $url;
22
+
23
+ $this->settings = get_option('wcml_exchange_rate_service_' . $this->id, array() );
24
+
25
+ if( $this->is_key_required() ){
26
+ $this->api_key = $this->get_setting( 'api-key' );
27
+ }
28
+
29
+ }
30
+
31
+ public function get_name(){
32
+ return $this->name;
33
+ }
34
+
35
+ public function get_url(){
36
+ return $this->url;
37
+ }
38
+
39
+ /**
40
+ * @param $from
41
+ * @param $to
42
+ * @return mixed
43
+ */
44
+ public abstract function get_rates( $from, $to );
45
+
46
+ /**
47
+ * @return array
48
+ */
49
+ public function get_settings(){
50
+ return $this->settings;
51
+ }
52
+
53
+ /**
54
+ *
55
+ */
56
+ private function save_settings(){
57
+ update_option('wcml_exchange_rate_service_' . $this->id, $this->settings);
58
+ }
59
+
60
+ /**
61
+ * @param $key string
62
+ * @return mixed|null
63
+ */
64
+ public function get_setting( $key ){
65
+ return isset( $this->settings[$key] ) ? $this->settings[$key] : null;
66
+ }
67
+
68
+ /**
69
+ * @param $key string
70
+ * @param $value mixed
71
+ */
72
+ public function save_setting( $key, $value ){
73
+ $this->settings[$key] = $value;
74
+ $this->save_settings();
75
+ }
76
+
77
+ /**
78
+ * @return bool
79
+ */
80
+ public function is_key_required(){
81
+ return static::REQUIRES_KEY;
82
+ }
83
+
84
+ /**
85
+ * @param $error_message string
86
+ */
87
+ public function save_last_error( $error_message ){
88
+ $this->save_setting( 'last_error',
89
+ array(
90
+ 'text' => $error_message,
91
+ 'time' => date_i18n( 'F j, Y g:i a', current_time( 'timestamp' ) )
92
+ )
93
+ );
94
+ }
95
+
96
+ /**
97
+ *
98
+ */
99
+ public function clear_last_error(){
100
+ $this->save_setting( 'last_error', false );
101
+ }
102
+
103
+ /**
104
+ * @return mixed
105
+ */
106
+ public function get_last_error(){
107
+ return isset( $this->settings['last_error'] ) ? $this->settings['last_error'] : false;
108
+ }
109
+
110
+
111
+ }
inc/admin-menus/class-wcml-setup.php CHANGED
@@ -61,10 +61,20 @@ class WCML_Setup {
61
  }
62
 
63
  private function setup_redirect(){
 
64
  if ( get_transient( '_wcml_activation_redirect' ) ) {
65
  delete_transient( '_wcml_activation_redirect' );
66
 
67
- if ( ( ! empty( $_GET['page'] ) && in_array( $_GET['page'], array( 'wcml-setup' ) ) ) || is_network_admin() || isset( $_GET['activate-multi'] ) || ! current_user_can( 'manage_options' ) ) {
 
 
 
 
 
 
 
 
 
68
  return;
69
  }
70
 
61
  }
62
 
63
  private function setup_redirect(){
64
+
65
  if ( get_transient( '_wcml_activation_redirect' ) ) {
66
  delete_transient( '_wcml_activation_redirect' );
67
 
68
+ $woocommerce_notices = get_option( 'woocommerce_admin_notices', array() );
69
+ $woocommerce_setup_not_run = in_array( 'install', $woocommerce_notices );
70
+
71
+ if (
72
+ ( ! empty( $_GET['page'] ) && in_array( $_GET['page'], array( 'wcml-setup' ) ) ) ||
73
+ is_network_admin() ||
74
+ isset( $_GET['activate-multi'] ) ||
75
+ ! current_user_can( 'manage_options' ) ||
76
+ $woocommerce_setup_not_run
77
+ ) {
78
  return;
79
  }
80
 
inc/class-wcml-cart-removed-items-widget.php ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WCML_Cart_Removed_Items_Widget extends WP_Widget {
4
+
5
+ function __construct() {
6
+
7
+ $widget_opt = array(
8
+ 'description' => __( 'Shows a list of the products that existed in the cart before the cart is reset on the front end after switching the language or the currency. It will be hidden when there are no products to show.', 'woocommerce-multilingual' ),
9
+ );
10
+
11
+ parent::__construct(
12
+ 'wcml_cart_deleted_items',
13
+ __( 'Products before cart reset', 'woocommerce-multilingual' ),
14
+ $widget_opt
15
+ );
16
+
17
+ }
18
+
19
+ function widget( $args, $instance ) {
20
+
21
+ echo $args[ 'before_widget' ];
22
+
23
+ do_action( 'wcml_removed_cart_items' );
24
+
25
+ echo $args[ 'after_widget' ];
26
+ }
27
+
28
+ }
inc/class-wcml-cart.php CHANGED
@@ -4,27 +4,173 @@ class WCML_Cart
4
 
5
  private $woocommerce_wpml;
6
  private $sitepress;
 
7
 
8
- public function __construct( &$woocommerce_wpml, &$sitepress )
9
  {
10
  $this->woocommerce_wpml = $woocommerce_wpml;
11
  $this->sitepress = $sitepress;
 
12
 
13
- //cart widget
14
- add_action( 'wp_ajax_woocommerce_get_refreshed_fragments', array( $this, 'wcml_refresh_fragments' ), 0 );
15
- add_action( 'wp_ajax_woocommerce_add_to_cart', array( $this, 'wcml_refresh_fragments' ), 0 );
16
- add_action( 'wp_ajax_nopriv_woocommerce_get_refreshed_fragments', array( $this, 'wcml_refresh_fragments' ), 0 );
17
- add_action( 'wp_ajax_nopriv_woocommerce_add_to_cart', array( $this, 'wcml_refresh_fragments' ), 0 );
18
 
19
- //cart
20
- add_action( 'woocommerce_before_calculate_totals', array( $this, 'woocommerce_calculate_totals' ), 100 );
21
- add_action( 'woocommerce_get_cart_item_from_session', array( $this, 'translate_cart_contents' ), 10, 3 );
22
- add_action( 'woocommerce_cart_loaded_from_session', array( $this, 'translate_cart_subtotal' ) );
23
- add_action( 'woocommerce_before_checkout_process', array( $this, 'wcml_refresh_cart_total' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
- add_filter('woocommerce_paypal_args', array($this, 'filter_paypal_args'));
 
 
 
 
 
 
 
26
 
27
- $this->localize_flat_rates_shipping_classes();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  }
29
 
30
  public function wcml_refresh_fragments(){
@@ -36,7 +182,6 @@ class WCML_Cart
36
  * Update cart and cart session when switch language
37
  */
38
  public function woocommerce_calculate_totals( $cart, $currency = false ){
39
- global $woocommerce;
40
 
41
  $current_language = $this->sitepress->get_current_language();
42
  $new_cart_data = array();
@@ -44,9 +189,10 @@ class WCML_Cart
44
  foreach( $cart->cart_contents as $key => $cart_item ){
45
  $tr_product_id = apply_filters( 'translate_object_id', $cart_item[ 'product_id' ], 'product', false, $current_language );
46
  //translate custom attr labels in cart object
47
- if( isset( $cart_item[ 'data' ]->product_attributes ) ){
 
48
  foreach( $cart_item[ 'data' ]->product_attributes as $attr_key => $product_attribute ){
49
- if( !$product_attribute[ 'is_taxonomy' ] ){
50
  $cart->cart_contents[ $key ][ 'data' ]->product_attributes[ $attr_key ][ 'name' ] = $this->woocommerce_wpml->strings->translated_attribute_label(
51
  $product_attribute[ 'name' ],
52
  $product_attribute[ 'name' ],
@@ -63,7 +209,7 @@ class WCML_Cart
63
  $attribute,
64
  $cart_item[ 'variation_id' ],
65
  $current_language,
66
- $cart_item[ 'data' ]->parent->id,
67
  $tr_product_id
68
  );
69
  }
@@ -74,7 +220,9 @@ class WCML_Cart
74
  }
75
 
76
  if( $cart_item[ 'product_id' ] == $tr_product_id ){
77
- $new_cart_data[ $key ] = apply_filters( 'wcml_cart_contents_not_changed', $cart->cart_contents[$key], $key, $current_language );
 
 
78
  continue;
79
  }
80
 
@@ -95,25 +243,21 @@ class WCML_Cart
95
  }
96
 
97
  if( !is_null( $tr_product_id ) ){
98
- $cart_item_data = $this->get_cart_item_data_from_cart( $cart->cart_contents[ $key ] );
99
- $new_key = $woocommerce->cart->generate_cart_id(
100
- $cart->cart_contents[ $key ][ 'product_id' ],
101
- $cart->cart_contents[ $key ][ 'variation_id' ],
102
- $cart->cart_contents[ $key ][ 'variation' ],
103
- $cart_item_data );
104
  $cart->cart_contents = apply_filters( 'wcml_update_cart_contents_lang_switch', $cart->cart_contents, $key, $new_key, $current_language );
105
  $new_cart_data[ $new_key ] = $cart->cart_contents[ $key ];
 
106
  $new_cart_data = apply_filters( 'wcml_cart_contents', $new_cart_data, $cart->cart_contents, $key, $new_key );
107
- }
108
  }
109
 
110
  $cart->cart_contents = $this->wcml_check_on_duplicate_products_in_cart( $new_cart_data );
111
- $woocommerce->session->cart = $cart;
112
- return $cart;
113
  }
114
 
115
  public function wcml_check_on_duplicate_products_in_cart( $cart_contents ){
116
- global $woocommerce;
117
 
118
  $exists_products = array();
119
  remove_action( 'woocommerce_before_calculate_totals', array( $this, 'woocommerce_calculate_totals' ), 100 );
@@ -125,19 +269,12 @@ class WCML_Cart
125
  }
126
 
127
  $quantity = $cart_content['quantity'];
128
- // unset unnecessary data to generate id to check
129
- unset( $cart_content['quantity'] );
130
- unset( $cart_content['line_total'] );
131
- unset( $cart_content['line_subtotal'] );
132
- unset( $cart_content['line_tax'] );
133
- unset( $cart_content['line_subtotal_tax'] );
134
- unset( $cart_content['line_tax_data'] );
135
-
136
- $search_key = md5( serialize( $cart_content ) );
137
  if( array_key_exists( $search_key, $exists_products ) ){
138
  unset( $cart_contents[ $key ] );
139
  $cart_contents[ $exists_products[ $search_key ] ][ 'quantity' ] = $cart_contents[ $exists_products[ $search_key ] ][ 'quantity' ] + $quantity;
140
- $woocommerce->cart->calculate_totals();
141
  }else{
142
  $exists_products[ $search_key ] = $key;
143
  }
@@ -177,25 +314,46 @@ class WCML_Cart
177
  return $attr_translation;
178
  }
179
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
180
  //get cart_item_data from existing cart array ( from session )
181
  public function get_cart_item_data_from_cart( $cart_contents ){
182
  unset( $cart_contents[ 'product_id' ] );
183
  unset( $cart_contents[ 'variation_id' ] );
184
  unset( $cart_contents[ 'variation' ] );
185
  unset( $cart_contents[ 'quantity' ] );
 
 
 
 
 
186
  unset( $cart_contents[ 'data' ] );
187
 
188
  return apply_filters( 'wcml_filter_cart_item_data', $cart_contents );
189
  }
190
 
191
- public function translate_cart_contents( $item, $values, $key ) {
192
  // translate the product id and product data
193
  $item[ 'product_id' ] = apply_filters( 'translate_object_id', $item[ 'product_id' ], 'product', true );
194
  if ($item[ 'variation_id' ]) {
195
  $item[ 'variation_id' ] = apply_filters( 'translate_object_id',$item[ 'variation_id' ], 'product_variation', true );
196
  }
197
  $product_id = $item[ 'variation_id' ] ? $item[ 'variation_id' ] : $item[ 'product_id' ];
198
- $item[ 'data' ]->post->post_title = get_the_title( $item[ 'product_id' ] );
 
199
  return $item;
200
  }
201
 
@@ -226,11 +384,10 @@ class WCML_Cart
226
 
227
 
228
  public function localize_flat_rates_shipping_classes(){
229
- global $woocommerce;
230
 
231
  if(is_ajax() && isset($_POST['action']) && $_POST['action'] == 'woocommerce_update_order_review'){
232
- $woocommerce->shipping->load_shipping_methods();
233
- $shipping_methods = $woocommerce->shipping->get_shipping_methods();
234
  foreach($shipping_methods as $method){
235
  if(isset($method->flat_rate_option)){
236
  add_filter('option_' . $method->flat_rate_option, array($this, 'translate_shipping_class'));
4
 
5
  private $woocommerce_wpml;
6
  private $sitepress;
7
+ private $woocommerce;
8
 
9
+ public function __construct( &$woocommerce_wpml, &$sitepress, &$woocommerce )
10
  {
11
  $this->woocommerce_wpml = $woocommerce_wpml;
12
  $this->sitepress = $sitepress;
13
+ $this->woocommerce = $woocommerce;
14
 
15
+ if( $this->woocommerce_wpml->settings[ 'cart_sync' ][ 'currency_switch' ] == WCML_CART_CLEAR || $this->woocommerce_wpml->settings[ 'cart_sync' ][ 'lang_switch' ] == WCML_CART_CLEAR ){
16
+ $this->enqueue_dialog_ui();
 
 
 
17
 
18
+ add_action( 'wcml_removed_cart_items', array( $this, 'wcml_removed_cart_items_widget' ) );
19
+ add_action( 'wp_ajax_wcml_cart_clear_removed_items', array( $this, 'wcml_cart_clear_removed_items' ) );
20
+ add_action( 'wp_ajax_nopriv_wcml_cart_clear_removed_items', array( $this, 'wcml_cart_clear_removed_items' ) );
21
+
22
+ add_filter( 'wcml_switch_currency_exception', array( $this, 'cart_switching_currency' ), 10, 3 );
23
+ add_action( 'wcml_before_switch_currency', array( $this, 'switching_currency_empty_cart_if_needed' ), 10, 2 );
24
+ }
25
+ else{
26
+ //cart widget
27
+ add_action( 'wp_ajax_woocommerce_get_refreshed_fragments', array( $this, 'wcml_refresh_fragments' ), 0 );
28
+ add_action( 'wp_ajax_woocommerce_add_to_cart', array( $this, 'wcml_refresh_fragments' ), 0 );
29
+ add_action( 'wp_ajax_nopriv_woocommerce_get_refreshed_fragments', array( $this, 'wcml_refresh_fragments' ), 0 );
30
+ add_action( 'wp_ajax_nopriv_woocommerce_add_to_cart', array( $this, 'wcml_refresh_fragments' ), 0 );
31
+
32
+ //cart
33
+ add_action( 'woocommerce_before_calculate_totals', array( $this, 'woocommerce_calculate_totals' ), 100 );
34
+ add_action( 'woocommerce_get_cart_item_from_session', array( $this, 'translate_cart_contents' ), 10 );
35
+ add_action( 'woocommerce_cart_loaded_from_session', array( $this, 'translate_cart_subtotal' ) );
36
+ add_action( 'woocommerce_before_checkout_process', array( $this, 'wcml_refresh_cart_total' ) );
37
+
38
+ add_filter('woocommerce_paypal_args', array($this, 'filter_paypal_args'));
39
+
40
+ $this->localize_flat_rates_shipping_classes();
41
+ }
42
+
43
+ }
44
+
45
+ public function enqueue_dialog_ui(){
46
+
47
+ wp_enqueue_script( 'jquery-ui-dialog' );
48
+ wp_enqueue_style( 'wp-jquery-ui-dialog' );
49
+
50
+ }
51
+
52
+ public function wcml_removed_cart_items_widget( $args = array() ){
53
+
54
+ if( !empty( $this->woocommerce->session ) ){
55
+ $removed_cart_items = new WCML_Removed_Cart_Items_UI( $args, $this->woocommerce_wpml, $this->sitepress, $this->woocommerce );
56
+ $preview = $removed_cart_items->get_view();
57
+
58
+ if ( !isset($args['echo']) || $args['echo'] ) {
59
+ echo $preview;
60
+ } else {
61
+ return $preview;
62
+ }
63
+ }
64
+
65
+ }
66
+
67
+ public function switching_currency_empty_cart_if_needed( $currency, $force_switch ){
68
+ if( $force_switch && $this->woocommerce_wpml->settings[ 'cart_sync' ][ 'currency_switch' ] == WCML_CART_CLEAR ) {
69
+ $this->empty_cart_if_needed('currency_switch');
70
+ $this->woocommerce->session->set('wcml_switched_type', 'currency');
71
+ }
72
+ }
73
+
74
+ public function empty_cart_if_needed( $switching_type ){
75
+
76
+ if( $this->woocommerce_wpml->settings[ 'cart_sync' ][ $switching_type ] == WCML_CART_CLEAR ){
77
+ $removed_products = $this->woocommerce->session->get( 'wcml_removed_items' ) ? maybe_unserialize( $this->woocommerce->session->get( 'wcml_removed_items' ) ) : array();
78
+
79
+ foreach( WC()->cart->get_cart_for_session() as $item_key => $cart ){
80
+ if( !in_array( $cart[ 'product_id' ], $removed_products ) ){
81
+ $removed_products[] = $cart[ 'product_id' ];
82
+ }
83
+ WC()->cart->remove_cart_item( $item_key );
84
+ }
85
+
86
+ if( !empty( $this->woocommerce->session ) ){
87
+ $this->woocommerce->session->set( 'wcml_removed_items', serialize( $removed_products ) );
88
+ }
89
+ }
90
+ }
91
+
92
+ public function wcml_cart_clear_removed_items( ){
93
+
94
+ $nonce = filter_input( INPUT_POST, 'wcml_nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
95
+ if(!$nonce || !wp_verify_nonce($nonce, 'wcml_clear_removed_items')){
96
+ die('Invalid nonce');
97
+ }
98
+
99
+ $this->woocommerce->session->__unset( 'wcml_removed_items' );
100
+ $this->woocommerce->session->__unset( 'wcml_switched_type' );
101
+ }
102
+
103
+ public function cart_switching_currency( $exc, $current_currency, $new_currency, $return = false ){
104
+
105
+ $cart_for_session = WC()->cart->get_cart_for_session();
106
+ if( $this->woocommerce_wpml->settings[ 'cart_sync' ][ 'currency_switch' ] == WCML_CART_SYNC || empty( $cart_for_session ) ){
107
+ return $exc;
108
+ }
109
+
110
+ $dialog_title = __( 'Switching currency?', 'woocommerce-multilingual');
111
+ $confirmation_message = __( 'Your cart is not empty! After you switched the currency, all items from the cart will be removed and you have to add them again.', 'woocommerce-multilingual');
112
+ $stay_in = sprintf( __( 'Keep using %s', 'woocommerce-multilingual'), $current_currency );
113
+ $switch_to = __( 'Proceed', 'woocommerce-multilingual');
114
+
115
+ ob_start();
116
+ $this->cart_alert( $dialog_title, $confirmation_message, $switch_to, $stay_in, $new_currency, $current_currency );
117
+ $html = ob_get_contents();
118
+ ob_end_clean();
119
 
120
+ if( $return ){
121
+ return array( 'prevent_switching' => $html );
122
+ }else{
123
+ echo json_encode( array( 'prevent_switching' => $html ) );
124
+ }
125
+
126
+ return true;
127
+ }
128
 
129
+ public function cart_alert( $dialog_title, $confirmation_message, $switch_to, $stay_in, $switch_to_value, $stay_in_value = false, $language_switch = false ){
130
+ ?>
131
+ <div id="wcml-cart-dialog-confirm" title="<?php echo $dialog_title ?>">
132
+ <p><?php echo $confirmation_message; ?></p>
133
+ </div>
134
+
135
+ <script type="text/javascript">
136
+ jQuery( document).ready( function(){
137
+ jQuery( "#wcml-cart-dialog-confirm" ).dialog({
138
+ resizable: false,
139
+ draggable: false,
140
+ height: "auto",
141
+ width: 500,
142
+ modal: true,
143
+ closeOnEscape: false,
144
+ dialogClass: "wcml-cart-dialog",
145
+ open: function(event, ui) {
146
+ jQuery(".ui-dialog-titlebar-close", ui.dialog | ui).hide();
147
+ },
148
+ buttons: {
149
+ "<?php echo $switch_to; ?>": function() {
150
+ jQuery( this ).dialog( "close" );
151
+ <?php if( $language_switch ): ?>
152
+ window.location = '<?php echo $switch_to_value; ?>';
153
+ <?php else: ?>
154
+ jQuery('.wcml_currency_switcher').parent().find('img').remove();
155
+ wcml_load_currency( "<?php echo $switch_to_value; ?>", true );
156
+ <?php endif; ?>
157
+
158
+ },
159
+ "<?php echo $stay_in; ?>": function() {
160
+ jQuery( this ).dialog( "close" );
161
+ <?php if( $language_switch ): ?>
162
+ window.location = '<?php echo $stay_in_value; ?>';
163
+ <?php else: ?>
164
+ jQuery('.wcml_currency_switcher').parent().find('img').remove();
165
+ jQuery('.wcml_currency_switcher').removeAttr('disabled');
166
+ jQuery('.wcml_currency_switcher').val( '<?php echo $stay_in_value; ?>' );
167
+ <?php endif; ?>
168
+ }
169
+ }
170
+ });
171
+ });
172
+ </script>
173
+ <?php
174
  }
175
 
176
  public function wcml_refresh_fragments(){
182
  * Update cart and cart session when switch language
183
  */
184
  public function woocommerce_calculate_totals( $cart, $currency = false ){
 
185
 
186
  $current_language = $this->sitepress->get_current_language();
187
  $new_cart_data = array();
189
  foreach( $cart->cart_contents as $key => $cart_item ){
190
  $tr_product_id = apply_filters( 'translate_object_id', $cart_item[ 'product_id' ], 'product', false, $current_language );
191
  //translate custom attr labels in cart object
192
+
193
+ if( version_compare( WC_VERSION , '2.7', '<' ) && isset( $cart_item[ 'data' ]->product_attributes ) ){
194
  foreach( $cart_item[ 'data' ]->product_attributes as $attr_key => $product_attribute ){
195
+ if( isset( $product_attribute[ 'is_taxonomy' ]) && !$product_attribute[ 'is_taxonomy' ] ){
196
  $cart->cart_contents[ $key ][ 'data' ]->product_attributes[ $attr_key ][ 'name' ] = $this->woocommerce_wpml->strings->translated_attribute_label(
197
  $product_attribute[ 'name' ],
198
  $product_attribute[ 'name' ],
209
  $attribute,
210
  $cart_item[ 'variation_id' ],
211
  $current_language,
212
+ $cart_item[ 'product_id' ],
213
  $tr_product_id
214
  );
215
  }
220
  }
221
 
222
  if( $cart_item[ 'product_id' ] == $tr_product_id ){
223
+
224
+ $new_key = $this->wcml_generate_cart_key( $cart->cart_contents, $key );
225
+ $new_cart_data[ $new_key ] = apply_filters( 'wcml_cart_contents_not_changed', $cart->cart_contents[$key], $key, $current_language );
226
  continue;
227
  }
228
 
243
  }
244
 
245
  if( !is_null( $tr_product_id ) ){
246
+
247
+ $new_key = $this->wcml_generate_cart_key( $cart->cart_contents, $key );
 
 
 
 
248
  $cart->cart_contents = apply_filters( 'wcml_update_cart_contents_lang_switch', $cart->cart_contents, $key, $new_key, $current_language );
249
  $new_cart_data[ $new_key ] = $cart->cart_contents[ $key ];
250
+
251
  $new_cart_data = apply_filters( 'wcml_cart_contents', $new_cart_data, $cart->cart_contents, $key, $new_key );
252
+ }
253
  }
254
 
255
  $cart->cart_contents = $this->wcml_check_on_duplicate_products_in_cart( $new_cart_data );
256
+ $this->woocommerce->session->cart = $cart->cart_contents;
257
+ return $cart->cart_contents;
258
  }
259
 
260
  public function wcml_check_on_duplicate_products_in_cart( $cart_contents ){
 
261
 
262
  $exists_products = array();
263
  remove_action( 'woocommerce_before_calculate_totals', array( $this, 'woocommerce_calculate_totals' ), 100 );
269
  }
270
 
271
  $quantity = $cart_content['quantity'];
272
+
273
+ $search_key = $this->wcml_generate_cart_key( $cart_contents, $key );
 
 
 
 
 
 
 
274
  if( array_key_exists( $search_key, $exists_products ) ){
275
  unset( $cart_contents[ $key ] );
276
  $cart_contents[ $exists_products[ $search_key ] ][ 'quantity' ] = $cart_contents[ $exists_products[ $search_key ] ][ 'quantity' ] + $quantity;
277
+ $this->woocommerce->cart->calculate_totals();
278
  }else{
279
  $exists_products[ $search_key ] = $key;
280
  }
314
  return $attr_translation;
315
  }
316
 
317
+ public function wcml_generate_cart_key( $cart_contents, $key ){
318
+ $cart_item_data = $this->get_cart_item_data_from_cart( $cart_contents[ $key ] );
319
+
320
+ return $this->woocommerce->cart->generate_cart_id(
321
+ $cart_contents[ $key ][ 'product_id' ],
322
+ $cart_contents[ $key ][ 'variation_id' ],
323
+ $cart_contents[ $key ][ 'variation' ],
324
+ (array) apply_filters( 'woocommerce_add_cart_item_data',
325
+ $cart_item_data,
326
+ $cart_contents[ $key ][ 'product_id' ],
327
+ $cart_contents[ $key ][ 'variation_id' ]
328
+ )
329
+ );
330
+ }
331
+
332
  //get cart_item_data from existing cart array ( from session )
333
  public function get_cart_item_data_from_cart( $cart_contents ){
334
  unset( $cart_contents[ 'product_id' ] );
335
  unset( $cart_contents[ 'variation_id' ] );
336
  unset( $cart_contents[ 'variation' ] );
337
  unset( $cart_contents[ 'quantity' ] );
338
+ unset( $cart_contents[ 'line_total' ] );
339
+ unset( $cart_contents[ 'line_subtotal' ] );
340
+ unset( $cart_contents[ 'line_tax' ] );
341
+ unset( $cart_contents[ 'line_subtotal_tax' ] );
342
+ unset( $cart_contents[ 'line_tax_data' ] );
343
  unset( $cart_contents[ 'data' ] );
344
 
345
  return apply_filters( 'wcml_filter_cart_item_data', $cart_contents );
346
  }
347
 
348
+ public function translate_cart_contents( $item ) {
349
  // translate the product id and product data
350
  $item[ 'product_id' ] = apply_filters( 'translate_object_id', $item[ 'product_id' ], 'product', true );
351
  if ($item[ 'variation_id' ]) {
352
  $item[ 'variation_id' ] = apply_filters( 'translate_object_id',$item[ 'variation_id' ], 'product_variation', true );
353
  }
354
  $product_id = $item[ 'variation_id' ] ? $item[ 'variation_id' ] : $item[ 'product_id' ];
355
+ $item[ 'data' ]->post->post_title = get_the_title( $product_id );
356
+
357
  return $item;
358
  }
359
 
384
 
385
 
386
  public function localize_flat_rates_shipping_classes(){
 
387
 
388
  if(is_ajax() && isset($_POST['action']) && $_POST['action'] == 'woocommerce_update_order_review'){
389
+ $this->woocommerce->shipping->load_shipping_methods();
390
+ $shipping_methods = $this->woocommerce->shipping->get_shipping_methods();
391
  foreach($shipping_methods as $method){
392
  if(isset($method->flat_rate_option)){
393
  add_filter('option_' . $method->flat_rate_option, array($this, 'translate_shipping_class'));
inc/class-wcml-emails.php CHANGED
@@ -65,7 +65,16 @@ class WCML_Emails{
65
 
66
  add_filter( 'get_post_metadata', array( $this, 'filter_payment_method_string' ), 10, 4 );
67
 
68
- if( !isset( $_GET['post_type'] ) || $_GET['post_type'] != 'shop_order' ){
 
 
 
 
 
 
 
 
 
69
  add_filter( 'woocommerce_order_items_meta_get_formatted', array( $this, 'filter_formatted_items' ), 10, 2 );
70
  }
71
  }
65
 
66
  add_filter( 'get_post_metadata', array( $this, 'filter_payment_method_string' ), 10, 4 );
67
 
68
+ if(
69
+ (
70
+ !isset( $_GET['post_type'] ) ||
71
+ $_GET['post_type'] != 'shop_order'
72
+ ) &&
73
+ (
74
+ !isset( $_GET[ 'action' ] ) ||
75
+ !in_array( $_GET['action'] , array( 'woocommerce_mark_order_complete', 'woocommerce_mark_order_status', 'mark_processing' ) )
76
+ )
77
+ ){
78
  add_filter( 'woocommerce_order_items_meta_get_formatted', array( $this, 'filter_formatted_items' ), 10, 2 );
79
  }
80
  }
inc/class-wcml-endpoints.php CHANGED
@@ -85,7 +85,7 @@ class WCML_Endpoints{
85
  $string = icl_get_string_id( $endpoint, 'WooCommerce Endpoints', $key );
86
 
87
  if( !$string && function_exists( 'icl_register_string' ) ){
88
- do_action('wpml_register_single_string', 'WooCommerce Endpoints', $key, $endpoint );
89
  }else{
90
  $this->endpoints_strings[] = $string;
91
  }
@@ -151,8 +151,11 @@ class WCML_Endpoints{
151
 
152
  foreach( $endpoints as $key => $endpoint ){
153
  if( isset($wp->query_vars[$key]) ){
154
- if( in_array( $key, array( 'pay', 'order-received' ) ) ){
155
- $endpoint = get_option( 'woocommerce_checkout_'.str_replace( '-','_',$key).'_endpoint' );
 
 
 
156
  }else{
157
  $endpoint = get_option( 'woocommerce_myaccount_'.str_replace( '-','_',$key).'_endpoint' );
158
  }
85
  $string = icl_get_string_id( $endpoint, 'WooCommerce Endpoints', $key );
86
 
87
  if( !$string && function_exists( 'icl_register_string' ) ){
88
+ do_action( 'wpml_register_single_string', 'WooCommerce Endpoints', $key, $endpoint );
89
  }else{
90
  $this->endpoints_strings[] = $string;
91
  }
151
 
152
  foreach( $endpoints as $key => $endpoint ){
153
  if( isset($wp->query_vars[$key]) ){
154
+ if( $key === 'order-pay' ){
155
+ $endpoint = get_option( 'woocommerce_checkout_pay_endpoint' );
156
+ $p .= isset( $_SERVER[ 'QUERY_STRING' ] ) ? '?'.$_SERVER[ 'QUERY_STRING' ] : '';
157
+ }elseif( $key === 'order-received' ){
158
+ $endpoint = get_option( 'woocommerce_checkout_order_received_endpoint' );
159
  }else{
160
  $endpoint = get_option( 'woocommerce_myaccount_'.str_replace( '-','_',$key).'_endpoint' );
161
  }
inc/class-wcml-orders.php CHANGED
@@ -13,7 +13,7 @@ class WCML_Orders{
13
  public function __construct( &$woocommerce_wpml, &$sitepress ){
14
  $this->woocommerce_wpml = $woocommerce_wpml;
15
  $this->sitepress = $sitepress;
16
-
17
  add_action('init', array($this, 'init'));
18
 
19
  //checkout page
@@ -33,7 +33,7 @@ class WCML_Orders{
33
  add_filter('the_comments', array($this, 'get_filtered_comments'));
34
  add_filter('gettext',array($this, 'filtered_woocommerce_new_order_note_data'),10,3);
35
 
36
- add_filter( 'woocommerce_order_get_items', array( $this, 'woocommerce_order_get_items' ), 10 );
37
 
38
  add_action( 'woocommerce_process_shop_order_meta', array( $this, 'set_order_language_backend'), 10, 2 );
39
  add_action( 'woocommerce_order_actions_start', array( $this, 'order_language_dropdown' ), 11 ); //after order currency drop-down
@@ -93,11 +93,16 @@ class WCML_Orders{
93
 
94
  }
95
 
96
- function woocommerce_order_get_items( $items ){
97
 
98
  if( isset( $_GET[ 'post' ] ) && get_post_type( $_GET[ 'post' ] ) == 'shop_order' ) {
99
  // on order edit page use admin default language
100
  $language_to_filter = $this->sitepress->get_user_admin_language( get_current_user_id(), true );
 
 
 
 
 
101
  }else{
102
  $language_to_filter = $this->sitepress->get_current_language();
103
  }
@@ -110,7 +115,7 @@ class WCML_Orders{
110
  $tr_product_id = apply_filters( 'translate_object_id', $item_data, 'product', false, $language_to_filter );
111
  if( !is_null( $tr_product_id ) ){
112
  $items[ $index ][ $key ] = $tr_product_id;
113
- $items[ $index ][ 'name'] = wc_get_product( $tr_product_id )->get_title();
114
  }
115
  }
116
  if( $key == 'variation_id' ){
@@ -150,7 +155,7 @@ class WCML_Orders{
150
  $tr_product_id = apply_filters( 'translate_object_id', $item_product_id, 'product', false, $language_to_filter );
151
  if( !is_null( $tr_product_id ) ){
152
  $item->set_product_id( $tr_product_id );
153
- $item->set_name( wc_get_product( $tr_product_id )->get_title() );
154
  }
155
  $tr_variation_id = apply_filters( 'translate_object_id', $item->get_variation_id(), 'product_variation', false, $language_to_filter );
156
  if( !is_null( $tr_variation_id ) ){
@@ -182,7 +187,6 @@ class WCML_Orders{
182
  }
183
  }
184
 
185
-
186
  return $items;
187
 
188
  }
@@ -251,9 +255,9 @@ class WCML_Orders{
251
 
252
  // Fix for shipping update on the checkout page.
253
  function fix_shipping_update($amount){
254
- global $post;
255
 
256
- if($this->sitepress->get_current_language() !== $this->sitepress->get_default_language() && $post->ID == $this->checkout_page_id()){
257
 
258
  $_SESSION['icl_checkout_shipping_amount'] = $amount;
259
 
13
  public function __construct( &$woocommerce_wpml, &$sitepress ){
14
  $this->woocommerce_wpml = $woocommerce_wpml;
15
  $this->sitepress = $sitepress;
16
+
17
  add_action('init', array($this, 'init'));
18
 
19
  //checkout page
33
  add_filter('the_comments', array($this, 'get_filtered_comments'));
34
  add_filter('gettext',array($this, 'filtered_woocommerce_new_order_note_data'),10,3);
35
 
36
+ add_filter( 'woocommerce_order_get_items', array( $this, 'woocommerce_order_get_items' ), 10, 2 );
37
 
38
  add_action( 'woocommerce_process_shop_order_meta', array( $this, 'set_order_language_backend'), 10, 2 );
39
  add_action( 'woocommerce_order_actions_start', array( $this, 'order_language_dropdown' ), 11 ); //after order currency drop-down
93
 
94
  }
95
 
96
+ function woocommerce_order_get_items( $items, $order ){
97
 
98
  if( isset( $_GET[ 'post' ] ) && get_post_type( $_GET[ 'post' ] ) == 'shop_order' ) {
99
  // on order edit page use admin default language
100
  $language_to_filter = $this->sitepress->get_user_admin_language( get_current_user_id(), true );
101
+ }elseif( isset( $_GET[ 'action' ] ) && ( $_GET['action'] == 'woocommerce_mark_order_complete' || $_GET['action'] == 'woocommerce_mark_order_status' || $_GET['action'] == 'mark_processing') ){
102
+ //backward compatibility for WC < 2.7
103
+ $order_id = method_exists( 'WC_Order', 'get_id' ) ? $order->get_id() : $order->id;
104
+ $order_language = get_post_meta( $order_id, 'wpml_language', true );
105
+ $language_to_filter = $order_language ? $order_language : $this->sitepress->get_default_language();
106
  }else{
107
  $language_to_filter = $this->sitepress->get_current_language();
108
  }
115
  $tr_product_id = apply_filters( 'translate_object_id', $item_data, 'product', false, $language_to_filter );
116
  if( !is_null( $tr_product_id ) ){
117
  $items[ $index ][ $key ] = $tr_product_id;
118
+ $items[ $index ][ 'name'] = get_post( $tr_product_id )->post_title;
119
  }
120
  }
121
  if( $key == 'variation_id' ){
155
  $tr_product_id = apply_filters( 'translate_object_id', $item_product_id, 'product', false, $language_to_filter );
156
  if( !is_null( $tr_product_id ) ){
157
  $item->set_product_id( $tr_product_id );
158
+ $item->set_name( get_post( $tr_product_id )->post_title );
159
  }
160
  $tr_variation_id = apply_filters( 'translate_object_id', $item->get_variation_id(), 'product_variation', false, $language_to_filter );
161
  if( !is_null( $tr_variation_id ) ){
187
  }
188
  }
189
 
 
190
  return $items;
191
 
192
  }
255
 
256
  // Fix for shipping update on the checkout page.
257
  function fix_shipping_update($amount){
258
+ global $sitepress, $post;
259
 
260
+ if($sitepress->get_current_language() !== $sitepress->get_default_language() && $post->ID == $this->checkout_page_id()){
261
 
262
  $_SESSION['icl_checkout_shipping_amount'] = $amount;
263
 
inc/class-wcml-products.php CHANGED
@@ -87,11 +87,20 @@ class WCML_Products{
87
  }
88
 
89
  public function is_variable_product( $product_id ){
 
 
 
 
 
90
  $get_variation_term_taxonomy_ids = $this->wpdb->get_col( "SELECT tt.term_taxonomy_id FROM {$this->wpdb->terms} AS t LEFT JOIN {$this->wpdb->term_taxonomy} AS tt ON t.term_id = tt.term_id WHERE t.name = 'variable' AND tt.taxonomy = 'product_type'" );
91
  $get_variation_term_taxonomy_ids = apply_filters( 'wcml_variation_term_taxonomy_ids',(array)$get_variation_term_taxonomy_ids );
92
 
93
  $is_variable_product = $this->wpdb->get_var( $this->wpdb->prepare( "SELECT count(object_id) FROM {$this->wpdb->term_relationships} WHERE object_id = %d AND term_taxonomy_id IN (".join(',',$get_variation_term_taxonomy_ids).")",$product_id ) );
94
- return apply_filters( 'wcml_is_variable_product', $is_variable_product, $product_id );
 
 
 
 
95
  }
96
 
97
  public function is_grouped_product($product_id){
87
  }
88
 
89
  public function is_variable_product( $product_id ){
90
+ $cache_key = $product_id;
91
+ $cache_group = 'is_variable_product';
92
+ $temp_is_variable = wp_cache_get( $cache_key, $cache_group );
93
+ if( $temp_is_variable ) return $temp_is_variable;
94
+
95
  $get_variation_term_taxonomy_ids = $this->wpdb->get_col( "SELECT tt.term_taxonomy_id FROM {$this->wpdb->terms} AS t LEFT JOIN {$this->wpdb->term_taxonomy} AS tt ON t.term_id = tt.term_id WHERE t.name = 'variable' AND tt.taxonomy = 'product_type'" );
96
  $get_variation_term_taxonomy_ids = apply_filters( 'wcml_variation_term_taxonomy_ids',(array)$get_variation_term_taxonomy_ids );
97
 
98
  $is_variable_product = $this->wpdb->get_var( $this->wpdb->prepare( "SELECT count(object_id) FROM {$this->wpdb->term_relationships} WHERE object_id = %d AND term_taxonomy_id IN (".join(',',$get_variation_term_taxonomy_ids).")",$product_id ) );
99
+ $is_variable_product = apply_filters( 'wcml_is_variable_product', $is_variable_product, $product_id );
100
+
101
+ wp_cache_set( $cache_key, $is_variable_product, $cache_group );
102
+
103
+ return $is_variable_product;
104
  }
105
 
106
  public function is_grouped_product($product_id){
inc/class-wcml-reports.php CHANGED
@@ -249,8 +249,17 @@ class WCML_Reports{
249
  public function filter_reports_stock_query( $query_from ){
250
  global $wpdb, $sitepress;
251
 
252
- $query_from = preg_replace("/WHERE/", "LEFT JOIN {$wpdb->prefix}icl_translations AS t ON posts.ID = t.element_id WHERE", $query_from);
253
- $query_from .= " AND t.element_type IN ( 'post_product', 'post_product_variation' ) AND t.language_code = '".$sitepress->get_current_language()."'";
 
 
 
 
 
 
 
 
 
254
 
255
  return $query_from;
256
  }
249
  public function filter_reports_stock_query( $query_from ){
250
  global $wpdb, $sitepress;
251
 
252
+ $current_language = $sitepress->get_current_language();
253
+
254
+ if( $current_language !== 'all' ){
255
+ $query_from = preg_replace("/WHERE/",
256
+ "LEFT JOIN {$wpdb->prefix}icl_translations AS t
257
+ ON posts.ID = t.element_id
258
+ WHERE", $query_from);
259
+
260
+ $query_from .= " AND t.element_type IN ( 'post_product', 'post_product_variation' ) AND t.language_code = '".$current_language."'";
261
+ }
262
+
263
 
264
  return $query_from;
265
  }
inc/class-wcml-requests.php CHANGED
@@ -3,7 +3,7 @@ class WCML_Requests{
3
 
4
  function __construct(){
5
 
6
- add_action('init', array($this, 'run'));
7
 
8
 
9
  }
@@ -24,12 +24,28 @@ class WCML_Requests{
24
  $wcml_file_path_sync = filter_input( INPUT_POST, 'wcml_file_path_sync', FILTER_SANITIZE_NUMBER_INT );
25
 
26
  $woocommerce_wpml->settings['file_path_sync'] = $wcml_file_path_sync;
 
 
 
 
27
  $woocommerce_wpml->update_settings();
28
 
29
- $new_value =$wcml_file_path_sync == 0?2:$wcml_file_path_sync;
30
  $sitepress_settings['translation-management']['custom_fields_translation']['_downloadable_files'] = $new_value;
31
  $sitepress_settings['translation-management']['custom_fields_translation']['_file_paths'] = $new_value;
 
32
  $sitepress->save_settings($sitepress_settings);
 
 
 
 
 
 
 
 
 
 
 
33
  }
34
 
35
  if( isset( $_GET[ 'wcml_action' ] ) ){
3
 
4
  function __construct(){
5
 
6
+ add_action('init', array($this, 'run') );
7
 
8
 
9
  }
24
  $wcml_file_path_sync = filter_input( INPUT_POST, 'wcml_file_path_sync', FILTER_SANITIZE_NUMBER_INT );
25
 
26
  $woocommerce_wpml->settings['file_path_sync'] = $wcml_file_path_sync;
27
+
28
+ $woocommerce_wpml->settings['cart_sync']['lang_switch'] = intval( filter_input( INPUT_POST, 'cart_sync_lang', FILTER_SANITIZE_NUMBER_INT ) );
29
+ $woocommerce_wpml->settings['cart_sync']['currency_switch'] = intval( filter_input( INPUT_POST, 'cart_sync_currencies', FILTER_SANITIZE_NUMBER_INT ) );
30
+
31
  $woocommerce_wpml->update_settings();
32
 
33
+ $new_value = $wcml_file_path_sync == 0 ? 2 :$wcml_file_path_sync;
34
  $sitepress_settings['translation-management']['custom_fields_translation']['_downloadable_files'] = $new_value;
35
  $sitepress_settings['translation-management']['custom_fields_translation']['_file_paths'] = $new_value;
36
+
37
  $sitepress->save_settings($sitepress_settings);
38
+
39
+ $message = array(
40
+ 'id' => 'wcml-settings-saved',
41
+ 'text' => __('Your settings have been saved.', 'woocommerce-multilingual' ),
42
+ 'group' => 'wcml-settings',
43
+ 'admin_notice' => true,
44
+ 'limit_to_page' => true,
45
+ 'classes' => array('updated', 'notice', 'notice-success'),
46
+ 'show_once' => true
47
+ );
48
+ ICL_AdminNotifier::add_message( $message );
49
  }
50
 
51
  if( isset( $_GET[ 'wcml_action' ] ) ){
inc/class-wcml-resources.php CHANGED
@@ -51,7 +51,7 @@ class WCML_Resources {
51
  wp_enqueue_style( 'wcml_op' );
52
  }
53
 
54
- wp_register_style( 'wcml_admin', WCML_PLUGIN_URL . '/res/css/admin.css', null, WCML_VERSION );
55
  wp_enqueue_style( 'wcml_admin' );
56
  }
57
 
@@ -68,6 +68,19 @@ class WCML_Resources {
68
  'jquery-ui-resizable'
69
  ), WCML_VERSION );
70
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  if ( self::$is_wpml_wcml_page ) {
72
 
73
  wp_register_script( 'jquery-cookie', WCML_PLUGIN_URL . '/res/js/jquery.cookie' . WCML_JS_MIN . '.js', array('jquery'), WCML_VERSION );
@@ -96,6 +109,8 @@ class WCML_Resources {
96
  if ( self::$page == 'wpml-wcml' && self::$tab == 'multi-currency' ) {
97
  wp_register_script( 'multi-currency', WCML_PLUGIN_URL . '/res/js/multi-currency' . WCML_JS_MIN . '.js', array('jquery', 'jquery-ui-sortable'), WCML_VERSION, true );
98
  wp_enqueue_script( 'multi-currency' );
 
 
99
  }
100
 
101
  if ( self::$page == 'wpml-wcml' && self::$tab == 'product-attributes' ) {
51
  wp_enqueue_style( 'wcml_op' );
52
  }
53
 
54
+ wp_register_style( 'wcml_admin', WCML_PLUGIN_URL . '/res/css/admin.css', array( 'wp-pointer' ), WCML_VERSION );
55
  wp_enqueue_style( 'wcml_admin' );
56
  }
57
 
68
  'jquery-ui-resizable'
69
  ), WCML_VERSION );
70
 
71
+ wp_enqueue_script(
72
+ 'wcml-pointer',
73
+ WCML_PLUGIN_URL . '/res/js/pointer' . WCML_JS_MIN . '.js',
74
+ array( 'wp-pointer' ),
75
+ WCML_VERSION,
76
+ true
77
+ );
78
+
79
+ wp_register_script( 'wcml-front-scripts', WCML_PLUGIN_URL . '/res/js/front-scripts' . WCML_JS_MIN . '.js', array(
80
+ 'jquery'
81
+ ), WCML_VERSION );
82
+ wp_enqueue_script( 'wcml-front-scripts' );
83
+
84
  if ( self::$is_wpml_wcml_page ) {
85
 
86
  wp_register_script( 'jquery-cookie', WCML_PLUGIN_URL . '/res/js/jquery.cookie' . WCML_JS_MIN . '.js', array('jquery'), WCML_VERSION );
109
  if ( self::$page == 'wpml-wcml' && self::$tab == 'multi-currency' ) {
110
  wp_register_script( 'multi-currency', WCML_PLUGIN_URL . '/res/js/multi-currency' . WCML_JS_MIN . '.js', array('jquery', 'jquery-ui-sortable'), WCML_VERSION, true );
111
  wp_enqueue_script( 'multi-currency' );
112
+ wp_register_script( 'exchange-rates', WCML_PLUGIN_URL . '/res/js/exchange-rates' . WCML_JS_MIN . '.js', array('jquery'), WCML_VERSION, true );
113
+ wp_enqueue_script( 'exchange-rates' );
114
  }
115
 
116
  if ( self::$page == 'wpml-wcml' && self::$tab == 'product-attributes' ) {
inc/class-wcml-store-pages.php CHANGED
@@ -324,19 +324,19 @@ class WCML_Store_Pages{
324
 
325
  switch( $page ){
326
  case 'woocommerce_shop_page_id':
327
- $page_title = __( 'Shop', 'woocommerce-multilingual');
328
  break;
329
  case 'woocommerce_cart_page_id':
330
- $page_title = __( 'Cart', 'woocommerce-multilingual');
331
  break;
332
  case 'woocommerce_checkout_page_id':
333
- $page_title = __( 'Checkout', 'woocommerce-multilingual');
334
  break;
335
  case 'woocommerce_myaccount_page_id':
336
- $page_title = __( 'My Account', 'woocommerce-multilingual');
337
  break;
338
  default:
339
- $page_title = __( $orig_page->post_title, 'woocommerce-multilingual');
340
  break;
341
  }
342
 
324
 
325
  switch( $page ){
326
  case 'woocommerce_shop_page_id':
327
+ $page_title = $mis_lang !== 'en' ? __( 'Shop', 'woocommerce-multilingual') : 'Shop';
328
  break;
329
  case 'woocommerce_cart_page_id':
330
+ $page_title = $mis_lang !== 'en' ? __( 'Cart', 'woocommerce-multilingual') : 'Cart';
331
  break;
332
  case 'woocommerce_checkout_page_id':
333
+ $page_title = $mis_lang !== 'en' ? __( 'Checkout', 'woocommerce-multilingual') : 'Checkout';
334
  break;
335
  case 'woocommerce_myaccount_page_id':
336
+ $page_title = $mis_lang !== 'en' ? __( 'My Account', 'woocommerce-multilingual') : 'My Account';
337
  break;
338
  default:
339
+ $page_title = $mis_lang !== 'en' ? translate( $orig_page->post_title, 'woocommerce-multilingual') : $orig_page->post_title;
340
  break;
341
  }
342
 
inc/class-wcml-terms.php CHANGED
@@ -24,8 +24,6 @@ class WCML_Terms{
24
  add_action('created_term', array($this, 'translated_terms_status_update'), 10,3);
25
  add_action('edit_term', array($this, 'translated_terms_status_update'), 10,3);
26
  add_action('wp_ajax_wcml_update_term_translated_warnings', array( $this, 'wcml_update_term_translated_warnings'));
27
- add_action('wp_ajax_wcml_ingore_taxonomy_translation', array( $this, 'wcml_ingore_taxonomy_translation'));
28
- add_action('wp_ajax_wcml_uningore_taxonomy_translation', array( $this, 'wcml_uningore_taxonomy_translation'));
29
 
30
  add_action('created_term', array( $this, 'set_flag_for_variation_on_attribute_update'), 10, 3);
31
 
@@ -95,24 +93,14 @@ class WCML_Terms{
95
  $taxonomies = $taxonomies + array_keys(get_taxonomies(array('object_type'=>array('product_variations')),'objects'));
96
  $taxonomies = array_unique($taxonomies);
97
  $taxonomy = isset($_GET['taxonomy']) ? $_GET['taxonomy'] : false;
98
- if($taxonomy && in_array($taxonomy, $taxonomies)){
99
  $taxonomy_obj = get_taxonomy($taxonomy);
100
- $language = isset($_GET['lang']) ? $_GET['lang'] : false;
101
- if(empty($language) && isset($_GET['tag_ID'])){
102
- $tax_id = $this->wpdb->get_var($this->wpdb->prepare("SELECT term_taxonomy_id FROM {$this->wpdb->term_taxonomy} WHERE term_id=%d AND taxonomy=%s", $_GET['tag_ID'], $taxonomy));
103
- $language = $this->sitepress->get_language_for_element($tax_id, 'tax_' . $taxonomy);
104
- }
105
- if(empty($language)){
106
- $language = $this->sitepress->get_default_language();
107
- }
108
-
109
  $message = sprintf(__('To translate %s please use the %s translation%s page, inside the %sWooCommerce Multilingual admin%s.', 'woocommerce-multilingual'),
110
  $taxonomy_obj->labels->name,
111
  '<strong><a href="' . admin_url('admin.php?page=wpml-wcml&tab=' . $taxonomy ) . '">' . $taxonomy_obj->labels->singular_name, '</a></strong>',
112
  '<strong><a href="' . admin_url('admin.php?page=wpml-wcml">'), '</a></strong>');
113
 
114
  echo '<div class="updated"><p>' . $message . '</p></div>';
115
-
116
  }
117
 
118
  }
@@ -274,71 +262,6 @@ class WCML_Terms{
274
  exit;
275
 
276
  }
277
-
278
- public function wcml_ingore_taxonomy_translation(){
279
- $nonce = filter_input( INPUT_POST, 'wcml_nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
280
- if(!$nonce || !wp_verify_nonce($nonce, 'wcml_ingore_taxonomy_translation_nonce')){
281
- die('Invalid nonce');
282
- }
283
-
284
- $ret = array();
285
-
286
- $taxonomy = filter_input( INPUT_POST, 'taxonomy', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
287
-
288
- $wcml_settings = $this->woocommerce_wpml->get_settings();
289
- $wcml_settings['untranstaled_terms'][$taxonomy]['status'] = $this->NEW_TAXONOMY_IGNORED;
290
-
291
- $this->woocommerce_wpml->update_settings($wcml_settings);
292
-
293
- $ret['html'] = '<i class="otgs-ico-ok"></i> ';
294
- $ret['html'] .= sprintf(__('%s do not require translation.', 'woocommerce-multilingual'), get_taxonomy($taxonomy)->labels->name);
295
- $ret['html'] .= '<small class="actions">';
296
- $ret['html'] .= '<a href="#unignore-' . $taxonomy . '">' . __( 'Include to translation', 'woocommerce-multilingual' ) . '</a>';
297
- $ret['html'] .= '</small>';
298
-
299
- echo json_encode($ret);
300
- exit;
301
- }
302
-
303
- public function wcml_uningore_taxonomy_translation(){
304
- $nonce = filter_input( INPUT_POST, 'wcml_nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
305
- if(!$nonce || !wp_verify_nonce($nonce, 'wcml_ingore_taxonomy_translation_nonce')){
306
- die('Invalid nonce');
307
- }
308
-
309
- $ret = array();
310
-
311
- $taxonomy = filter_input( INPUT_POST, 'taxonomy', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
312
-
313
- $wcml_settings = $this->woocommerce_wpml->get_settings();
314
-
315
- if($wcml_settings['untranstaled_terms'][$taxonomy]['count'] > 0){
316
- $wcml_settings['untranstaled_terms'][$taxonomy]['status'] = $this->NEW_TAXONOMY_TERMS;
317
-
318
- $ret['html'] = '<i class="otgs-ico-warning-sign"></i> ';
319
- $ret['html'] .= sprintf( __( '%d %s are missing translations.', 'woocommerce-multilingual' ), $wcml_settings['untranstaled_terms'][ $taxonomy ]['count'], get_taxonomy( $taxonomy )->labels->name );
320
- $ret['html'] .= ' <a class="button-secondary" href="' . admin_url( 'admin.php?page=wpml-wcml&tab=' . $taxonomy ) . '">' . sprintf( __( 'Translate %s', 'woocommerce-multilingual' ), get_taxonomy( $taxonomy )->labels->name ) . '</a>';
321
- $ret['html'] .= '<small class="actions">';
322
- $ret['html'] .= '<a href="#ignore-' . $taxonomy . '">' . __( 'Exclude from translation', 'woocommerce-multilingual' ) . '</a>';
323
- $ret['html'] .= '</small>';
324
-
325
- $ret['warn'] = 1;
326
-
327
- }else{
328
- $wcml_settings['untranstaled_terms'][$taxonomy]['status'] = $this->ALL_TAXONOMY_TERMS_TRANSLATED;
329
-
330
- $ret['html'] = '<i class="otgs-ico-ok"></i> ';
331
- $ret['html'] .= sprintf(__('All %s are translated.', 'woocommerce-multilingual'), get_taxonomy($taxonomy)->labels->name);
332
-
333
- $ret['warn'] = 0;
334
- }
335
-
336
- $this->woocommerce_wpml->update_settings($wcml_settings);
337
-
338
-
339
- echo json_encode($ret);
340
- exit;
341
- }
342
 
343
  public function update_terms_translated_status($taxonomy){
344
 
24
  add_action('created_term', array($this, 'translated_terms_status_update'), 10,3);
25
  add_action('edit_term', array($this, 'translated_terms_status_update'), 10,3);
26
  add_action('wp_ajax_wcml_update_term_translated_warnings', array( $this, 'wcml_update_term_translated_warnings'));
 
 
27
 
28
  add_action('created_term', array( $this, 'set_flag_for_variation_on_attribute_update'), 10, 3);
29
 
93
  $taxonomies = $taxonomies + array_keys(get_taxonomies(array('object_type'=>array('product_variations')),'objects'));
94
  $taxonomies = array_unique($taxonomies);
95
  $taxonomy = isset($_GET['taxonomy']) ? $_GET['taxonomy'] : false;
96
+ if( $taxonomy && in_array( $taxonomy, $taxonomies ) ){
97
  $taxonomy_obj = get_taxonomy($taxonomy);
 
 
 
 
 
 
 
 
 
98
  $message = sprintf(__('To translate %s please use the %s translation%s page, inside the %sWooCommerce Multilingual admin%s.', 'woocommerce-multilingual'),
99
  $taxonomy_obj->labels->name,
100
  '<strong><a href="' . admin_url('admin.php?page=wpml-wcml&tab=' . $taxonomy ) . '">' . $taxonomy_obj->labels->singular_name, '</a></strong>',
101
  '<strong><a href="' . admin_url('admin.php?page=wpml-wcml">'), '</a></strong>');
102
 
103
  echo '<div class="updated"><p>' . $message . '</p></div>';
 
104
  }
105
 
106
  }
262
  exit;
263
 
264
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
265
 
266
  public function update_terms_translated_status($taxonomy){
267
 
inc/class-wcml-tp-support.php CHANGED
@@ -29,10 +29,9 @@ class WCML_TP_Support {
29
 
30
  $product = wc_get_product( $post->ID );
31
 
32
- //WC_Product::get_type() available from WooCommerce 2.4.0
33
- $product_type = method_exists( $product, 'get_type' ) ? $product->get_type() : $product->product_type;
34
 
35
- if ( ! empty( $product ) && $product_type == 'variable' ) {
36
 
37
  $attributes = $product->get_attributes();
38
 
@@ -133,10 +132,9 @@ class WCML_TP_Support {
133
  /** @var WC_Product_Variable $product */
134
  $product = wc_get_product( $post->ID );
135
 
136
- //WC_Product::get_type() available from WooCommerce 2.4.0
137
- $product_type = method_exists( $product, 'get_type' ) ? $product->get_type() : $product->product_type;
138
 
139
- if ( ! empty( $product ) && $product_type == 'variable' ) {
140
 
141
  $variations = $product->get_available_variations();
142
 
@@ -199,9 +197,7 @@ class WCML_TP_Support {
199
  public function append_slug_to_translation_package( $package, $post ) {
200
  if ( $post->post_type == 'product' ) {
201
 
202
- $product = wc_get_product( $post->ID );
203
-
204
- $this->add_to_package( $package, 'slug', urldecode( $product->post->post_name ) );
205
  }
206
 
207
  return $package;
@@ -212,9 +208,9 @@ class WCML_TP_Support {
212
 
213
  foreach ( $data as $data_key => $value ) {
214
  if ( $value['finished'] && isset( $value['field_type'] ) && 'slug' === $value['field_type'] ) {
215
- $product = wc_get_product( $post_id );
216
- if ( $product->post->post_type == 'product' ) {
217
- $new_slug = wp_unique_post_slug( $value['data'], $post_id, $product->post->post_status, $product->post->post_type, $product->post->post_parent );
218
  $wpdb->update( $wpdb->posts, array( 'post_name' => $new_slug ), array( 'ID' => $post_id ) );
219
  break;
220
  }
@@ -227,10 +223,9 @@ class WCML_TP_Support {
227
 
228
  if ( $post->post_type == 'product' ) {
229
 
230
- $product = wc_get_product( $post->ID );
231
  $woocommerce_wpml = woocommerce_wpml::instance();
232
- $product_images = $woocommerce_wpml->media->product_images_ids( $product->id );
233
- $product_images = $woocommerce_wpml->media->exclude_not_duplicated_attachments( $product_images, $product->id );
234
  foreach ( $product_images as $image_id ) {
235
  $attachment_data = $wpdb->get_row( $wpdb->prepare( "SELECT post_title,post_excerpt,post_content FROM {$wpdb->posts} WHERE ID = %d", $image_id ) );
236
  if ( ! $attachment_data ) {
29
 
30
  $product = wc_get_product( $post->ID );
31
 
32
+ $product_type = Deprecated_WC_Functions::get_product_type( $post->ID );
 
33
 
34
+ if ( ! empty( $product ) && $product_type === 'variable' ) {
35
 
36
  $attributes = $product->get_attributes();
37
 
132
  /** @var WC_Product_Variable $product */
133
  $product = wc_get_product( $post->ID );
134
 
135
+ $product_type = Deprecated_WC_Functions::get_product_type( $post->ID );
 
136
 
137
+ if ( ! empty( $product ) && $product_type === 'variable' ) {
138
 
139
  $variations = $product->get_available_variations();
140
 
197
  public function append_slug_to_translation_package( $package, $post ) {
198
  if ( $post->post_type == 'product' ) {
199
 
200
+ $this->add_to_package( $package, 'slug', urldecode( $post->post_name ) );
 
 
201
  }
202
 
203
  return $package;
208
 
209
  foreach ( $data as $data_key => $value ) {
210
  if ( $value['finished'] && isset( $value['field_type'] ) && 'slug' === $value['field_type'] ) {
211
+ $product = get_post( $post_id );
212
+ if ( $product->post_type == 'product' ) {
213
+ $new_slug = wp_unique_post_slug( sanitize_title( $value['data'] ), $post_id, $product->post_status, $product->post_type, $product->post_parent );
214
  $wpdb->update( $wpdb->posts, array( 'post_name' => $new_slug ), array( 'ID' => $post_id ) );
215
  break;
216
  }
223
 
224
  if ( $post->post_type == 'product' ) {
225
 
 
226
  $woocommerce_wpml = woocommerce_wpml::instance();
227
+ $product_images = $woocommerce_wpml->media->product_images_ids( $post->ID );
228
+ $product_images = $woocommerce_wpml->media->exclude_not_duplicated_attachments( $product_images, $post->ID );
229
  foreach ( $product_images as $image_id ) {
230
  $attachment_data = $wpdb->get_row( $wpdb->prepare( "SELECT post_title,post_excerpt,post_content FROM {$wpdb->posts} WHERE ID = %d", $image_id ) );
231
  if ( ! $attachment_data ) {
inc/class-wcml-troubleshooting.php CHANGED
@@ -128,7 +128,7 @@ class WCML_Troubleshooting{
128
  die('Invalid nonce');
129
  }
130
 
131
- $page = isset($_POST['page'])?$_POST['page']:0;
132
 
133
  global $woocommerce_wpml,$wpdb;
134
 
@@ -153,7 +153,7 @@ class WCML_Troubleshooting{
153
  die('Invalid nonce');
154
  }
155
 
156
- $page = isset($_POST['page'])?$_POST['page']:0;
157
 
158
  global $wpdb,$sitepress;
159
 
128
  die('Invalid nonce');
129
  }
130
 
131
+ $page = isset($_POST['page'])? intval( $_POST['page'] ) :0;
132
 
133
  global $woocommerce_wpml,$wpdb;
134
 
153
  die('Invalid nonce');
154
  }
155
 
156
+ $page = isset($_POST['page'])? intval( $_POST['page'] ):0;
157
 
158
  global $wpdb,$sitepress;
159
 
inc/class-wcml-upgrade.php CHANGED
@@ -17,6 +17,7 @@ class WCML_Upgrade{
17
  '3.8',
18
  '3.9',
19
  '3.9.1',
 
20
  );
21
 
22
  function __construct(){
@@ -517,10 +518,15 @@ class WCML_Upgrade{
517
  }
518
  }
519
 
520
- function upgrade_3_10(){
521
  $wcml_settings = get_option( '_wcml_settings' );
522
  $wcml_settings[ 'dismiss_tm_warning' ] = 0;
523
- update_option( '_wcml_settings', $wcml_settings );
 
 
 
 
524
  }
525
 
 
526
  }
17
  '3.8',
18
  '3.9',
19
  '3.9.1',
20
+ '4.0'
21
  );
22
 
23
  function __construct(){
518
  }
519
  }
520
 
521
+ function upgrade_4_0(){
522
  $wcml_settings = get_option( '_wcml_settings' );
523
  $wcml_settings[ 'dismiss_tm_warning' ] = 0;
524
+ $wcml_settings['cart_sync']['lang_switch'] = WCML_CART_SYNC;
525
+ $wcml_settings['cart_sync']['currency_switch'] = WCML_CART_SYNC;
526
+
527
+ update_option('_wcml_settings', $wcml_settings);
528
+
529
  }
530
 
531
+
532
  }
inc/class-wcml-wc-gateways.php CHANGED
@@ -3,8 +3,12 @@
3
  class WCML_WC_Gateways{
4
 
5
  private $current_language;
 
6
 
7
- function __construct( &$sitepress ){
 
 
 
8
 
9
  add_action( 'init', array( $this, 'init' ), 11 );
10
 
@@ -18,10 +22,16 @@ class WCML_WC_Gateways{
18
  }
19
 
20
  function init(){
 
21
 
22
  add_filter('woocommerce_gateway_title', array($this, 'translate_gateway_title'), 10, 2);
23
  add_filter('woocommerce_gateway_description', array($this, 'translate_gateway_description'), 10, 2);
24
 
 
 
 
 
 
25
  }
26
 
27
 
@@ -42,40 +52,11 @@ class WCML_WC_Gateways{
42
 
43
  if( isset( $gateway->id ) ){
44
  $gateway_id = $gateway->id;
45
-
46
- add_filter( 'woocommerce_settings_api_sanitized_fields_'.$gateway_id, array( $this, 'register_gateway_strings' ) );
47
  $this->translate_gateway_strings( $gateway );
48
  }
49
 
50
  }
51
 
52
- function register_gateway_strings( $fields ){
53
-
54
- $wc_payment_gateways = WC_Payment_Gateways::instance();
55
-
56
- foreach( $wc_payment_gateways->payment_gateways() as $gateway ){
57
- if( isset( $_POST['woocommerce_'.$gateway->id.'_enabled'] ) || isset( $_POST[ $gateway->id.'_enabled'] ) ){
58
- $gateway_id = $gateway->id;
59
- break;
60
- }
61
- }
62
-
63
- if( isset( $gateway_id ) ){
64
- do_action('wpml_register_single_string', 'woocommerce', $gateway_id .'_gateway_title', $fields['title'] );
65
-
66
- if( isset( $fields['description'] ) ) {
67
- do_action('wpml_register_single_string', 'woocommerce', $gateway_id . '_gateway_description', $fields['description']);
68
- }
69
-
70
- if( isset( $fields['instructions'] ) ){
71
- do_action('wpml_register_single_string', 'woocommerce', $gateway_id .'_gateway_instructions', $fields['instructions'] );
72
- }
73
- }
74
-
75
- return $fields;
76
- }
77
-
78
-
79
  function translate_gateway_strings( $gateway ){
80
 
81
  if( isset( $gateway->enabled ) && $gateway->enabled != 'no' ){
@@ -112,5 +93,95 @@ class WCML_WC_Gateways{
112
  return $instructions;
113
  }
114
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
 
116
  }
3
  class WCML_WC_Gateways{
4
 
5
  private $current_language;
6
+ private $sitepress;
7
 
8
+ function __construct( &$woocommerce_wpml, &$sitepress ){
9
+
10
+ $this->sitepress = $sitepress;
11
+ $this->woocommerce_wpml = $woocommerce_wpml;
12
 
13
  add_action( 'init', array( $this, 'init' ), 11 );
14
 
22
  }
23
 
24
  function init(){
25
+ global $pagenow;
26
 
27
  add_filter('woocommerce_gateway_title', array($this, 'translate_gateway_title'), 10, 2);
28
  add_filter('woocommerce_gateway_description', array($this, 'translate_gateway_description'), 10, 2);
29
 
30
+ if( is_admin() && $pagenow == 'admin.php' && isset( $_GET[ 'page' ] ) && $_GET[ 'page' ] == 'wc-settings' && isset( $_GET[ 'tab' ] ) && $_GET[ 'tab' ] == 'checkout' ){
31
+ add_action( 'admin_footer', array($this, 'show_language_links_for_gateways' ) );
32
+ $this->register_and_set_gateway_strings_language();
33
+ }
34
+
35
  }
36
 
37
 
52
 
53
  if( isset( $gateway->id ) ){
54
  $gateway_id = $gateway->id;
 
 
55
  $this->translate_gateway_strings( $gateway );
56
  }
57
 
58
  }
59
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  function translate_gateway_strings( $gateway ){
61
 
62
  if( isset( $gateway->enabled ) && $gateway->enabled != 'no' ){
93
  return $instructions;
94
  }
95
 
96
+ function show_language_links_for_gateways(){
97
+
98
+ $text_keys = array(
99
+ 'title',
100
+ 'description',
101
+ 'instructions'
102
+ );
103
+ $wc_payment_gateways = WC_Payment_Gateways::instance();
104
+
105
+ foreach( $wc_payment_gateways->payment_gateways() as $payment_gateway ) {
106
+
107
+ if( isset( $_GET['section'] ) && $_GET['section'] == $payment_gateway->id ){
108
+
109
+ foreach( $text_keys as $text_key ) {
110
+
111
+ if ( isset( $payment_gateway->settings[ $text_key ] ) ) {
112
+ $setting_value = $payment_gateway->settings[ $text_key ];
113
+ }elseif( $text_key === 'instructions' ){
114
+ $setting_value = $payment_gateway->description;
115
+ }else{
116
+ $setting_value = $payment_gateway->$text_key;
117
+ }
118
+
119
+ $input_name = $payment_gateway->plugin_id.$payment_gateway->id.'_'.$text_key;
120
+ $gateway_option = $payment_gateway->plugin_id.$payment_gateway->id.'_settings';
121
+
122
+ $lang_selector = new WPML_Simple_Language_Selector( $this->sitepress );
123
+ $language = $this->woocommerce_wpml->strings->get_string_language( $setting_value, 'woocommerce', $payment_gateway->id .'_gateway_'. $text_key );
124
+ if( is_null( $language ) ) {
125
+ $language = $this->sitepress->get_default_language();
126
+ }
127
+
128
+ $lang_selector->render( array(
129
+ 'id' => $gateway_option.'_'.$text_key.'_language_selector',
130
+ 'name' => 'wcml_lang-'.$gateway_option.'-'.$text_key,
131
+ 'selected' => $language,
132
+ 'show_please_select' => false,
133
+ 'echo' => true,
134
+ 'style' => 'width: 18%;float: left;margin-top: 3px;'
135
+ )
136
+ );
137
+
138
+ $st_page = admin_url( 'admin.php?page=' . WPML_ST_FOLDER . '/menu/string-translation.php&context=woocommerce&search='. esc_attr( $setting_value ) );
139
+ if( $text_key === 'title' || $payment_gateway->id === 'paypal' ){
140
+ $input_type = 'input';
141
+ }else{
142
+ $input_type = 'textarea';
143
+ }
144
+ ?>
145
+ <script>
146
+ var input = jQuery('<?php echo $input_type ?>[name="<?php echo $input_name ?>"]');
147
+ if ( input.length ) {
148
+ input.parent().append('<div class="translation_controls"></div>');
149
+ input.parent().find('.translation_controls').append('<a href="<?php echo $st_page ?>" style="margin-left: 10px"><?php _e('translations', 'woocommerce-multilingual') ?></a>');
150
+ jQuery('#<?php echo $gateway_option.'_'.$text_key.'_language_selector' ?>').prependTo( input.parent().find('.translation_controls') );
151
+ }
152
+ </script>
153
+ <?php }
154
+ }
155
+ }
156
+ }
157
+
158
+ function register_and_set_gateway_strings_language(){
159
+
160
+ foreach( $_POST as $key => $language ){
161
+
162
+ if( substr( $key, 0, 9 ) == 'wcml_lang' ){
163
+
164
+ $gateway_string = explode( '-', $key );
165
+
166
+ if( isset( $gateway_string[2] ) ){
167
+
168
+ $gateway_key = str_replace( '_settings', '', $gateway_string[1] );
169
+ $gateway_string_name = str_replace( 'woocommerce_', '', $gateway_key ) .'_gateway_'. $gateway_string[2];
170
+ $gateway_key .= '_'.$gateway_string[2];
171
+
172
+ $gateway_settings = get_option( $gateway_string[1], true );
173
+
174
+ $string_value = isset( $_POST[ $gateway_key ] ) ? $_POST[ $gateway_key ] : '';
175
+ $opt_string_value = isset( $gateway_settings[ $gateway_string[2] ] ) ? $gateway_settings[ $gateway_string[2] ] : $string_value;
176
+
177
+ $context = 'woocommerce';
178
+
179
+ do_action( 'wpml_register_single_string', $context, $gateway_string_name, $string_value, false, $this->woocommerce_wpml->strings->get_string_language( $opt_string_value, $context ) );
180
+
181
+ $this->woocommerce_wpml->strings->set_string_language( $string_value, $context, $gateway_string_name, $language );
182
+ }
183
+ }
184
+ }
185
+ }
186
 
187
  }
inc/class-wcml-wc-strings.php CHANGED
@@ -106,7 +106,7 @@ class WCML_WC_Strings{
106
 
107
  if($values){
108
 
109
- $parent = $values['data']->post->post_parent;
110
  $tr_product_id = apply_filters( 'translate_object_id', $values['product_id'], 'product', true );
111
  $trnsl_title = get_the_title($tr_product_id);
112
 
106
 
107
  if($values){
108
 
109
+ $parent = wp_get_post_parent_id( $values['product_id'] );
110
  $tr_product_id = apply_filters( 'translate_object_id', $values['product_id'], 'product', true );
111
  $trnsl_title = get_the_title($tr_product_id);
112
 
inc/class-wcml-widgets.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WCML_Widgets{
4
+
5
+ private $woocommerce_wpml;
6
+
7
+ public function __construct( &$woocommerce_wpml ) {
8
+ $this->woocommerce_wpml =& $woocommerce_wpml;
9
+
10
+ add_action( 'widgets_init', array($this, 'register_widgets' ) );
11
+
12
+ }
13
+
14
+ public function register_widgets(){
15
+
16
+ if( $this->woocommerce_wpml->settings[ 'enable_multi_currency' ] == WCML_MULTI_CURRENCIES_INDEPENDENT ){
17
+ register_widget( 'WCML_Currency_Switcher_Widget' );
18
+ }
19
+
20
+ if( $this->woocommerce_wpml->settings[ 'cart_sync' ][ 'currency_switch' ] == WCML_CART_CLEAR || $this->woocommerce_wpml->settings[ 'cart_sync' ][ 'lang_switch' ] == WCML_CART_CLEAR ){
21
+ register_widget( 'WCML_Cart_Removed_Items_Widget' );
22
+ }
23
+
24
+ }
25
+
26
+ }
inc/class-wcml-woocommerce-rest-api-support.php CHANGED
@@ -216,13 +216,13 @@ class WCML_WooCommerce_Rest_API_Support{
216
 
217
  $translated_product_id = apply_filters( 'translate_object_id', $item['product_id'], 'product', true, $lang );
218
  if( $translated_product_id ){
219
- $translated_product = new WC_Product( $translated_product_id );
220
  $order_data['line_items'][$k]['product_id'] = $translated_product_id;
221
- if( $translated_product->post->post_type == 'product_variation' ){
222
- $post_parent = get_post( $translated_product->post->post_parent );
223
  $post_name = $post_parent->post_title;
224
  } else {
225
- $post_name = $translated_product->post->post_title;
226
  }
227
  $order_data['line_items'][$k]['name'] = $post_name;
228
  }
216
 
217
  $translated_product_id = apply_filters( 'translate_object_id', $item['product_id'], 'product', true, $lang );
218
  if( $translated_product_id ){
219
+ $translated_product = get_post( $translated_product_id );
220
  $order_data['line_items'][$k]['product_id'] = $translated_product_id;
221
+ if( $translated_product->post_type == 'product_variation' ){
222
+ $post_parent = get_post( $translated_product->post_parent );
223
  $post_name = $post_parent->post_title;
224
  } else {
225
+ $post_name = $translated_product->post_title;
226
  }
227
  $order_data['line_items'][$k]['name'] = $post_name;
228
  }
inc/class-woocommerce-wpml.php CHANGED
@@ -75,6 +75,8 @@ class woocommerce_wpml {
75
 
76
  $this->xdomain_data = new WCML_xDomain_Data;
77
 
 
 
78
  add_action('init', array($this, 'init'),2);
79
 
80
  }
@@ -97,7 +99,7 @@ class woocommerce_wpml {
97
  return self::$_instance;
98
  }
99
  public function init(){
100
- global $sitepress, $wpdb;
101
 
102
  new WCML_Upgrade;
103
 
@@ -107,6 +109,7 @@ class woocommerce_wpml {
107
  WCML_Admin_Menus::set_up_menus( $this, $sitepress, $wpdb, $this->check_dependencies );
108
 
109
  if( !$this->check_dependencies ){
 
110
 
111
  wp_register_style( 'otgs-ico', WCML_PLUGIN_URL . '/res/css/otgs-ico.css', null, WCML_VERSION );
112
  wp_enqueue_style( 'otgs-ico');
@@ -158,11 +161,11 @@ class woocommerce_wpml {
158
  $this->orders = new WCML_Orders( $this, $sitepress );
159
  $this->strings = new WCML_WC_Strings;
160
  $this->shipping = new WCML_WC_Shipping( $sitepress );
161
- $this->gateways = new WCML_WC_Gateways( $sitepress );
162
  $this->currencies = new WCML_Currencies( $this );
163
  $this->url_translation = new WCML_Url_Translation ( $this, $sitepress );
164
  $this->requests = new WCML_Requests;
165
- $this->cart = new WCML_Cart( $this, $sitepress );
166
  $this->coupons = new WCML_Coupons( $this, $sitepress );
167
  $this->locale = new WCML_Locale( $this, $sitepress );
168
  $this->media = new WCML_Media( $this, $sitepress, $wpdb );
@@ -199,7 +202,11 @@ class woocommerce_wpml {
199
  'trnsl_interface' => 1,
200
  'currency_options' => array(),
201
  'currency_switcher_product_visibility' => 1,
202
- 'dismiss_tm_warning' => 0
 
 
 
 
203
  );
204
 
205
  if(empty($this->settings)){
75
 
76
  $this->xdomain_data = new WCML_xDomain_Data;
77
 
78
+ new WCML_Widgets( $this );
79
+
80
  add_action('init', array($this, 'init'),2);
81
 
82
  }
99
  return self::$_instance;
100
  }
101
  public function init(){
102
+ global $sitepress, $wpdb, $woocommerce;
103
 
104
  new WCML_Upgrade;
105
 
109
  WCML_Admin_Menus::set_up_menus( $this, $sitepress, $wpdb, $this->check_dependencies );
110
 
111
  if( !$this->check_dependencies ){
112
+ WCML_Capabilities::set_up_capabilities();
113
 
114
  wp_register_style( 'otgs-ico', WCML_PLUGIN_URL . '/res/css/otgs-ico.css', null, WCML_VERSION );
115
  wp_enqueue_style( 'otgs-ico');
161
  $this->orders = new WCML_Orders( $this, $sitepress );
162
  $this->strings = new WCML_WC_Strings;
163
  $this->shipping = new WCML_WC_Shipping( $sitepress );
164
+ $this->gateways = new WCML_WC_Gateways( $this, $sitepress );
165
  $this->currencies = new WCML_Currencies( $this );
166
  $this->url_translation = new WCML_Url_Translation ( $this, $sitepress );
167
  $this->requests = new WCML_Requests;
168
+ $this->cart = new WCML_Cart( $this, $sitepress, $woocommerce );
169
  $this->coupons = new WCML_Coupons( $this, $sitepress );
170
  $this->locale = new WCML_Locale( $this, $sitepress );
171
  $this->media = new WCML_Media( $this, $sitepress, $wpdb );
202
  'trnsl_interface' => 1,
203
  'currency_options' => array(),
204
  'currency_switcher_product_visibility' => 1,
205
+ 'dismiss_tm_warning' => 0,
206
+ 'cart_sync' => array(
207
+ 'lang_switch' => WCML_CART_SYNC,
208
+ 'currency_switch' => WCML_CART_SYNC
209
+ )
210
  );
211
 
212
  if(empty($this->settings)){
inc/constants.php CHANGED
@@ -7,4 +7,7 @@ define('WCML_MULTI_CURRENCIES_INDEPENDENT', 2);
7
  define( 'WCML_TRANSLATION_METHOD_MANUAL', 0);
8
  define( 'WCML_TRANSLATION_METHOD_EDITOR', 1);
9
 
 
 
 
10
  define( 'WCML_JS_MIN', defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min');
7
  define( 'WCML_TRANSLATION_METHOD_MANUAL', 0);
8
  define( 'WCML_TRANSLATION_METHOD_EDITOR', 1);
9
 
10
+ define( 'WCML_CART_CLEAR', 0);
11
+ define( 'WCML_CART_SYNC', 1);
12
+
13
  define( 'WCML_JS_MIN', defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min');
inc/currencies/class-wcml-admin-currency-selector.php CHANGED
@@ -45,15 +45,17 @@ class WCML_Admin_Currency_Selector{
45
  $order_currencies = $this->woocommerce_wpml->multi_currency->orders->get_orders_currencies();
46
  ?>
47
  <select id="dropdown_dashboard_currency" style="display: none; margin : 10px; ">
 
 
 
 
48
 
49
- <?php foreach($order_currencies as $currency => $count ): ?>
50
-
51
- <option value="<?php echo $currency ?>" <?php echo $current_dashboard_currency == $currency ? 'selected="selected"':''; ?>>
52
- <?php echo $wc_currencies[$currency]; ?>
53
- </option>
54
-
55
- <?php endforeach; ?>
56
 
 
 
57
  </select>
58
  <?php
59
 
45
  $order_currencies = $this->woocommerce_wpml->multi_currency->orders->get_orders_currencies();
46
  ?>
47
  <select id="dropdown_dashboard_currency" style="display: none; margin : 10px; ">
48
+ <?php if(empty($orders_currencies)): ?>
49
+ <option value=""><?php _e('Currency - no orders found', 'woocommerce-multilingual') ?></option>
50
+ <?php else: ?>
51
+ <?php foreach($order_currencies as $currency => $count ): ?>
52
 
53
+ <option value="<?php echo $currency ?>" <?php echo $current_dashboard_currency == $currency ? 'selected="selected"':''; ?>>
54
+ <?php echo $wc_currencies[$currency]; ?>
55
+ </option>
 
 
 
 
56
 
57
+ <?php endforeach; ?>
58
+ <?php endif; ?>
59
  </select>
60
  <?php
61
 
inc/currencies/class-wcml-currencies.php CHANGED
@@ -7,22 +7,12 @@ class WCML_Currencies{
7
  public function __construct( &$woocommerce_wpml ) {
8
  $this->woocommerce_wpml =& $woocommerce_wpml;
9
 
10
- add_action('widgets_init', array($this, 'register_currency_switcher_widget'));
11
-
12
  if( is_admin() ){
13
  add_action( 'update_option_woocommerce_currency', array( $this, 'update_default_currency' ), 10, 2 );
14
  }
15
 
16
  }
17
 
18
- public function register_currency_switcher_widget(){
19
-
20
- if( $this->woocommerce_wpml->settings['enable_multi_currency'] == WCML_MULTI_CURRENCIES_INDEPENDENT ){
21
- register_widget( 'WCML_Currency_Switcher_Widget' );
22
- }
23
-
24
- }
25
-
26
  public function update_default_currency( $old_value, $new_value ){
27
 
28
  $this->woocommerce_wpml->multi_currency = new WCML_Multi_Currency();
7
  public function __construct( &$woocommerce_wpml ) {
8
  $this->woocommerce_wpml =& $woocommerce_wpml;
9
 
 
 
10
  if( is_admin() ){
11
  add_action( 'update_option_woocommerce_currency', array( $this, 'update_default_currency' ), 10, 2 );
12
  }
13
 
14
  }
15
 
 
 
 
 
 
 
 
 
16
  public function update_default_currency( $old_value, $new_value ){
17
 
18
  $this->woocommerce_wpml->multi_currency = new WCML_Multi_Currency();
inc/currencies/class-wcml-currency-switcher.php CHANGED
@@ -104,7 +104,7 @@ class WCML_Currency_Switcher {
104
  if( $is_cart_or_checkout ){
105
  $show_currency_switcher = false;
106
  }elseif( is_product() ){
107
- $current_product_id = wc_get_product()->id;
108
  $original_product_language = $this->woocommerce_wpml->products->get_original_product_language( $current_product_id );
109
 
110
  $use_custom_prices = get_post_meta(
104
  if( $is_cart_or_checkout ){
105
  $show_currency_switcher = false;
106
  }elseif( is_product() ){
107
+ $current_product_id = get_post()->ID;
108
  $original_product_language = $this->woocommerce_wpml->products->get_original_product_language( $current_product_id );
109
 
110
  $use_custom_prices = get_post_meta(
inc/currencies/class-wcml-custom-prices.php CHANGED
@@ -19,7 +19,12 @@ class WCML_Custom_Prices{
19
 
20
  }
21
 
22
- add_action( 'woocommerce_get_children', array( $this, 'filter_product_variations_with_custom_prices' ), 10 );
 
 
 
 
 
23
  add_filter( 'loop_shop_post_in', array( $this, 'filter_products_with_custom_prices' ), 100 );
24
 
25
  }
19
 
20
  }
21
 
22
+ if( version_compare( WC_VERSION , '2.7', '<' ) ){
23
+ add_action( 'woocommerce_get_children', array( $this, 'filter_product_variations_with_custom_prices' ), 10 );
24
+ }else{
25
+ add_action( 'woocommerce_product_get_children', array( $this, 'filter_product_variations_with_custom_prices' ), 10 );
26
+ }
27
+
28
  add_filter( 'loop_shop_post_in', array( $this, 'filter_products_with_custom_prices' ), 100 );
29
 
30
  }
inc/currencies/class-wcml-exchange-rates.php ADDED
@@ -0,0 +1,345 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WCML_Exchange_Rates{
4
+
5
+ /**
6
+ * @var woocommerce_wpml
7
+ */
8
+ private $woocommerce_wpml;
9
+
10
+ /**
11
+ * @var array
12
+ */
13
+ private $services = array();
14
+
15
+ /**
16
+ * @var array
17
+ */
18
+ private $settings;
19
+
20
+ const cronjob_event = 'wcml_exchange_rates_update';
21
+
22
+ function __construct( $woocommerce_wpml ) {
23
+
24
+ $this->woocommerce_wpml =& $woocommerce_wpml;
25
+
26
+ $this->initialize_settings();
27
+
28
+ // Load built in services
29
+ $this->services['yahoo'] = new WCML_Exchange_Rates_YahooFinance();
30
+ $this->services['fixierio'] = new WCML_Exchange_Rates_Fixierio();
31
+ $this->services['currencylayer'] = new WCML_Exchange_Rates_Currencylayer();
32
+
33
+ if( is_admin() ){
34
+ add_action( 'wcml_saved_mc_options', array($this, 'update_exchange_rate_options' ) ); //before init
35
+ }
36
+
37
+ add_action( 'init', array( $this, 'init' ) );
38
+
39
+ }
40
+
41
+ public function init(){
42
+
43
+ if( $this->woocommerce_wpml->multi_currency->get_currencies() ){
44
+
45
+ if( is_admin() ){
46
+ add_action( 'wp_ajax_wcml_update_exchange_rates', array( $this, 'update_exchange_rates_ajax') );
47
+ }
48
+
49
+ add_filter( 'cron_schedules', array( $this, 'cron_schedules' ) );
50
+ add_action( self::cronjob_event, array( $this, 'update_exchange_rates' ) );
51
+
52
+ }
53
+
54
+ }
55
+
56
+ private function initialize_settings(){
57
+
58
+ if( !isset( $this->woocommerce_wpml->settings['multi_currency']['exchange_rates'] ) ){
59
+
60
+ $this->settings = array(
61
+ 'automatic' => 0,
62
+ 'service' => 'yahoo',
63
+ 'lifting_charge' => 0,
64
+ 'schedule' => 'manual',
65
+ 'week_day' => 1,
66
+ 'month_day' => 1
67
+ );
68
+
69
+ $this->save_settings();
70
+
71
+ } else {
72
+ $this->settings =& $this->woocommerce_wpml->settings['multi_currency']['exchange_rates'];
73
+ }
74
+
75
+ }
76
+
77
+ public function get_services(){
78
+ return $this->services;
79
+ }
80
+
81
+ /**
82
+ * @param $service_id string
83
+ * @param $service WCML_Exchange_Rate_Service
84
+ */
85
+ public function add_service( $service_id, $service ){
86
+ $this->services[ $service_id ] = $service;
87
+ }
88
+
89
+ public function get_settings(){
90
+ return $this->settings;
91
+ }
92
+
93
+ public function get_setting( $key ){
94
+ return isset( $this->settings[$key] ) ? $this->settings[$key] : null;
95
+ }
96
+
97
+ public function save_settings(){
98
+
99
+ $this->woocommerce_wpml->settings['multi_currency']['exchange_rates'] = $this->settings;
100
+ $this->woocommerce_wpml->update_settings();
101
+ }
102
+
103
+ public function save_setting( $key, $value ){
104
+ $this->settings[$key] = $value;
105
+ $this->save_settings();
106
+ }
107
+
108
+ public function update_exchange_rates_ajax(){
109
+
110
+ $response = array();
111
+
112
+ if( wp_create_nonce( 'update-exchange-rates' ) == $_POST['wcml_nonce'] ) {
113
+
114
+ try {
115
+
116
+ $rates = $this->update_exchange_rates();
117
+ $response['success'] = 1;
118
+ $response['last_updated'] = date_i18n( 'F j, Y g:i a', $this->settings['last_updated'] );
119
+ $response['rates'] = $rates;
120
+
121
+ } catch ( Exception $e ) {
122
+
123
+ $response['success'] = 0;
124
+ $response['error'] = $e->getMessage();
125
+ $response['service'] = $this->settings['service'];
126
+
127
+ }
128
+
129
+ } else {
130
+
131
+ $response['success'] = 0;
132
+ $response['error'] = 'Invalid nonce';
133
+
134
+ }
135
+
136
+ wp_send_json( $response );
137
+ }
138
+
139
+ public function update_exchange_rates(){
140
+
141
+ if( isset( $this->services[ $this->settings['service'] ]) ){
142
+ $service =& $this->services[ $this->settings['service'] ];
143
+
144
+ $currencies = $this->woocommerce_wpml->multi_currency->get_currency_codes();
145
+ $default_currency = get_option( 'woocommerce_currency' );
146
+ $secondary_currencies = array_diff( $currencies, array( $default_currency ) );
147
+
148
+ try{
149
+ $rates = $service->get_rates( $default_currency, $secondary_currencies );
150
+ } catch (Exception $e){
151
+ if( defined( 'WP_DEBUG_LOG' ) && WP_DEBUG_LOG ){
152
+ error_log( "Exchange rates update error (" . $this->settings['service'] . "): " . $e->getMessage() );
153
+ }
154
+ throw new Exception( $e->getMessage() );
155
+ return;
156
+ }
157
+
158
+ $this->apply_lifting_charge( $rates );
159
+
160
+ foreach( $rates as $to => $rate ){
161
+ if( $rate && is_numeric( $rate ) ){
162
+ $this->save_exchage_rate( $to, $rate );
163
+ }
164
+ }
165
+ }
166
+
167
+ $this->settings['last_updated'] = current_time( 'timestamp' );
168
+ $this->save_settings();
169
+
170
+ return $rates;
171
+ }
172
+
173
+ public function apply_lifting_charge( &$rates ){
174
+ foreach( $rates as $k => $rate ){
175
+ $rates[$k] = round( $rate * ( 1 + $this->settings['lifting_charge'] / 100 ), 4 );
176
+ }
177
+ }
178
+
179
+ private function save_exchage_rate( $currency, $rate ){
180
+
181
+ $this->woocommerce_wpml->settings['currency_options'][$currency]['previous_rate'] =
182
+ $this->woocommerce_wpml->settings['currency_options'][$currency]['rate'];
183
+ $this->woocommerce_wpml->settings['currency_options'][$currency]['rate'] = $rate;
184
+ $this->woocommerce_wpml->update_settings();
185
+
186
+ }
187
+
188
+ public function get_currency_rate( $currency ){
189
+ return $this->woocommerce_wpml->settings['currency_options'][$currency]['rate'];
190
+ }
191
+
192
+ public function update_exchange_rate_options( $post_data ){
193
+
194
+ if( isset( $post_data['exchange-rates-automatic'] ) && $post_data['exchange-rates-automatic'] ) {
195
+
196
+ $this->settings['automatic'] = intval($post_data['exchange-rates-automatic']);
197
+
198
+ if ( isset($post_data['exchange-rates-service']) ) {
199
+
200
+ // clear errors for replaced service
201
+ if( $post_data['exchange-rates-service'] != $this->settings['service'] ){
202
+ $this->services[$this->settings['service']]->clear_last_error();
203
+ }
204
+
205
+ $this->settings['service'] = sanitize_text_field( $post_data['exchange-rates-service'] );
206
+
207
+ }
208
+
209
+ if ( isset($post_data['services']) ) {
210
+
211
+ foreach ( $post_data['services'] as $service_id => $service_data ) {
212
+ foreach( $service_data as $key => $value ){
213
+ $this->services[$service_id]->save_setting( 'api-key', $value );
214
+ }
215
+ }
216
+
217
+ }
218
+
219
+ $this->settings['lifting_charge'] = is_numeric( $post_data['lifting_charge'] ) ? $post_data['lifting_charge'] : 0;
220
+
221
+ if ( isset($post_data['update-schedule']) ) {
222
+ $this->settings['schedule'] = sanitize_text_field( $post_data['update-schedule'] );
223
+ }
224
+
225
+ if ( isset($post_data['update-time']) ) {
226
+ $this->settings['time'] = sanitize_text_field( $post_data['update-time'] );
227
+ }
228
+
229
+ if ( isset($post_data['update-weekly-day']) ) {
230
+ $this->settings['week_day'] = sanitize_text_field( $post_data['update-weekly-day'] );
231
+ }
232
+
233
+ if ( isset($post_data['update-monthly-day']) ) {
234
+ $this->settings['month_day'] = sanitize_text_field( $post_data['update-monthly-day'] );
235
+ }
236
+
237
+ if ( $this->settings['schedule'] === 'manual' ) {
238
+ $this->delete_update_cronjob();
239
+ } else {
240
+ $this->enable_update_cronjob();
241
+ }
242
+
243
+ } else {
244
+ $this->settings['automatic'] = 0;
245
+ $this->delete_update_cronjob();
246
+ }
247
+
248
+ $this->save_settings();
249
+
250
+
251
+ }
252
+
253
+ public function enable_update_cronjob(){
254
+
255
+ $schedule = wp_get_schedule( self::cronjob_event );
256
+
257
+ if( $schedule != $this->settings['schedule'] ){
258
+ $this->delete_update_cronjob();
259
+ }
260
+
261
+
262
+ if( $this->settings['schedule'] == 'monthly' ){
263
+ $current_day = date('j');
264
+ $days_in_current_month = cal_days_in_month( CAL_GREGORIAN, date('n'), date('Y') );
265
+
266
+ if( $this->settings['month_day'] >= $current_day && $this->settings['month_day'] <= $days_in_current_month ){
267
+ $days = $this->settings['month_day'] - $current_day;
268
+ }else{
269
+ $days = $days_in_current_month - $current_day + $this->settings['month_day'];
270
+ }
271
+
272
+ $time_offset = time() + $days * 86400;
273
+ $schedule = 'wcml_' . $this->settings['schedule'] . '_on_' . $this->settings['month_day'];
274
+
275
+ }elseif( $this->settings['schedule'] == 'weekly' ){
276
+ $current_day = date('w');
277
+ if( $this->settings['week_day'] >= $current_day ){
278
+ $days = $this->settings['week_day'] - $current_day;
279
+ }else{
280
+ $days = 7 - $current_day + $this->settings['week_day'];
281
+ }
282
+
283
+ $time_offset = time() + $days * 86400;
284
+ $schedule = 'wcml_' . $this->settings['schedule'] . '_on_' . $this->settings['week_day'];
285
+
286
+ }else{
287
+ $time_offset = time();
288
+ $schedule = $this->settings['schedule'];
289
+
290
+ }
291
+
292
+ if( !wp_next_scheduled ( self::cronjob_event ) ){
293
+ wp_schedule_event( $time_offset, $schedule, self::cronjob_event );
294
+ }
295
+
296
+ }
297
+
298
+ public function delete_update_cronjob(){
299
+
300
+ wp_clear_scheduled_hook( self::cronjob_event );
301
+
302
+ }
303
+
304
+ public function cron_schedules( $schedules ) {
305
+
306
+ if( $this->settings['schedule'] == 'monthly' ){
307
+
308
+ $month_day = $this->settings['month_day'];
309
+ switch( $month_day ){
310
+ case 1: $month_day .= 'st'; break;
311
+ case 2: $month_day .= 'nd'; break;
312
+ case 3: $month_day .= 'rd'; break;
313
+ default: $month_day .= 'th'; break;
314
+ }
315
+
316
+ $current_month = date('n');
317
+ $days_in_current_month = cal_days_in_month( CAL_GREGORIAN, $current_month, date('Y') );
318
+ if( $this->settings['month_day'] >= date('j') && $this->settings['month_day'] <= $days_in_current_month ){
319
+ $interval = 3600 * 24 * $days_in_current_month;
320
+ }else{
321
+ $month_number = $current_month == 12 ? 1 : $current_month + 1;
322
+ $year_number = $current_month == 12 ? date('Y') + 1 : date('Y');
323
+ $interval = 3600 * 24 * cal_days_in_month( CAL_GREGORIAN, $month_number, $year_number );
324
+ }
325
+
326
+ $schedules['wcml_monthly_on_' . $this->settings['month_day']] = array(
327
+ 'interval' => $interval,
328
+ 'display' => sprintf( __( 'Monthly on the %s', 'woocommerce-multilingual' ), $month_day ),
329
+ );
330
+
331
+ } elseif( $this->settings['schedule'] == 'weekly' ){
332
+
333
+ global $wp_locale;
334
+ $week_day = $wp_locale->get_weekday( $this->settings['week_day'] );
335
+ $schedules['wcml_weekly_on_' . $this->settings['week_day']] = array(
336
+ 'interval' => 604800,
337
+ 'display' => sprintf( __( 'Weekly on %s', 'woocommerce-multilingual' ), $week_day ),
338
+ );
339
+
340
+ }
341
+
342
+ return $schedules;
343
+ }
344
+
345
+ }
inc/currencies/class-wcml-multi-currency-configuration.php CHANGED
@@ -36,11 +36,13 @@ class WCML_Multi_Currency_Configuration{
36
 
37
  if( check_admin_referer( 'wcml_mc_options', 'wcml_nonce' ) ){
38
 
39
- self::$woocommerce_wpml->settings['enable_multi_currency'] = isset($_POST['multi_currency']) ? intval($_POST['multi_currency']) : 0;
40
- self::$woocommerce_wpml->settings['display_custom_prices'] = isset($_POST['display_custom_prices']) ? intval($_POST['display_custom_prices']) : 0;
 
 
41
 
42
  //update default currency settings
43
- if( self::$woocommerce_wpml->settings['enable_multi_currency'] == WCML_MULTI_CURRENCIES_INDEPENDENT ){
44
 
45
  $options = array(
46
  'woocommerce_currency_pos' => 'position',
@@ -52,7 +54,7 @@ class WCML_Multi_Currency_Configuration{
52
  $woocommerce_currency = get_option('woocommerce_currency', true);
53
 
54
  foreach($options as $wc_key => $key){
55
- self::$woocommerce_wpml->settings['currency_options'][$woocommerce_currency][$key] = get_option( $wc_key, true );
56
  }
57
  }
58
 
@@ -62,16 +64,18 @@ class WCML_Multi_Currency_Configuration{
62
  $currency_switcher_format = sanitize_text_field( $currency_switcher_format );
63
  $currency_switcher_format = html_entity_decode( $currency_switcher_format );
64
 
65
- self::$woocommerce_wpml->settings['currency_switcher_style'] = sanitize_text_field( $_POST['currency_switcher_style'] );
66
- self::$woocommerce_wpml->settings['wcml_curr_sel_orientation'] = sanitize_text_field( $_POST['wcml_curr_sel_orientation'] );
67
- self::$woocommerce_wpml->settings['wcml_curr_template'] = $currency_switcher_format;
68
- self::$woocommerce_wpml->settings['currency_switcher_product_visibility'] = isset($_POST['currency_switcher_product_visibility']) ? intval( $_POST['currency_switcher_product_visibility'] ) : 0;
69
 
70
- self::$woocommerce_wpml->update_settings();
 
 
71
 
72
  $message = array(
73
  'id' => 'wcml-settings-saved',
74
- 'text' => __('Settings saved!', 'woocommerce-multilingual' ),
75
  'group' => 'wcml-multi-currency',
76
  'admin_notice' => true,
77
  'limit_to_page' => true,
@@ -80,7 +84,6 @@ class WCML_Multi_Currency_Configuration{
80
  );
81
  ICL_AdminNotifier::add_message( $message );
82
 
83
-
84
  }
85
 
86
  }
@@ -163,17 +166,19 @@ class WCML_Multi_Currency_Configuration{
163
  foreach( self::$multi_currency->currencies[$currency_code] as $key => $value ){
164
 
165
  if(isset($options[$key]) && $options[$key] != $value){
 
 
 
 
166
  self::$multi_currency->currencies[$currency_code][$key] = $options[$key];
167
  $changed = true;
168
- if($key == 'rate'){
169
- $rate_changed = true;
170
- }
171
  }
172
 
173
  }
174
 
175
  if($changed){
176
  if($rate_changed){
 
177
  self::$multi_currency->currencies[$currency_code]['updated'] = date('Y-m-d H:i:s');
178
  }
179
  self::$woocommerce_wpml->settings['currency_options'] = self::$multi_currency->currencies;
36
 
37
  if( check_admin_referer( 'wcml_mc_options', 'wcml_nonce' ) ){
38
 
39
+ $wcml_settings =& self::$woocommerce_wpml->settings;
40
+
41
+ $wcml_settings['enable_multi_currency'] = isset($_POST['multi_currency']) ? intval($_POST['multi_currency']) : 0;
42
+ $wcml_settings['display_custom_prices'] = isset($_POST['display_custom_prices']) ? intval($_POST['display_custom_prices']) : 0;
43
 
44
  //update default currency settings
45
+ if( $wcml_settings['enable_multi_currency'] == WCML_MULTI_CURRENCIES_INDEPENDENT ){
46
 
47
  $options = array(
48
  'woocommerce_currency_pos' => 'position',
54
  $woocommerce_currency = get_option('woocommerce_currency', true);
55
 
56
  foreach($options as $wc_key => $key){
57
+ $wcml_settings['currency_options'][$woocommerce_currency][$key] = get_option( $wc_key, true );
58
  }
59
  }
60
 
64
  $currency_switcher_format = sanitize_text_field( $currency_switcher_format );
65
  $currency_switcher_format = html_entity_decode( $currency_switcher_format );
66
 
67
+ $wcml_settings['currency_switcher_style'] = sanitize_text_field( $_POST['currency_switcher_style'] );
68
+ $wcml_settings['wcml_curr_sel_orientation'] = sanitize_text_field( $_POST['wcml_curr_sel_orientation'] );
69
+ $wcml_settings['wcml_curr_template'] = $currency_switcher_format;
70
+ $wcml_settings['currency_switcher_product_visibility'] = isset($_POST['currency_switcher_product_visibility']) ? intval( $_POST['currency_switcher_product_visibility'] ) : 0;
71
 
72
+ self::$woocommerce_wpml->update_settings( $wcml_settings );
73
+
74
+ do_action( 'wcml_saved_mc_options', $_POST );
75
 
76
  $message = array(
77
  'id' => 'wcml-settings-saved',
78
+ 'text' => __('Your settings have been saved.', 'woocommerce-multilingual' ),
79
  'group' => 'wcml-multi-currency',
80
  'admin_notice' => true,
81
  'limit_to_page' => true,
84
  );
85
  ICL_AdminNotifier::add_message( $message );
86
 
 
87
  }
88
 
89
  }
166
  foreach( self::$multi_currency->currencies[$currency_code] as $key => $value ){
167
 
168
  if(isset($options[$key]) && $options[$key] != $value){
169
+ if( $key == 'rate' ){
170
+ $previous_rate = self::$multi_currency->currencies[$currency_code][$key];
171
+ $rate_changed = true;
172
+ }
173
  self::$multi_currency->currencies[$currency_code][$key] = $options[$key];
174
  $changed = true;
 
 
 
175
  }
176
 
177
  }
178
 
179
  if($changed){
180
  if($rate_changed){
181
+ self::$multi_currency->currencies[$currency_code]['previous_rate'] = $previous_rate;
182
  self::$multi_currency->currencies[$currency_code]['updated'] = date('Y-m-d H:i:s');
183
  }
184
  self::$woocommerce_wpml->settings['currency_options'] = self::$multi_currency->currencies;
inc/currencies/class-wcml-multi-currency-orders.php CHANGED
@@ -121,7 +121,7 @@ class WCML_Multi_Currency_Orders{
121
 
122
  $the_order = new WC_Order( get_the_ID() );
123
  if( $the_order ){
124
- $order_currency = method_exists( $the_order, 'get_currency' ) ? $the_order->get_currency() : ( method_exists( $the_order, 'get_order_currency' ) ? $the_order->get_order_currency() : '' ) ;
125
 
126
  if( !$order_currency && isset( $_COOKIE[ '_wcml_order_currency' ] ) ){
127
  $order_currency = $_COOKIE[ '_wcml_order_currency' ];
@@ -314,7 +314,7 @@ class WCML_Multi_Currency_Orders{
314
  // handle currency in order emails before handled in woocommerce
315
  public function fix_currency_before_order_email($order){
316
 
317
- $order_currency = method_exists( $order, 'get_currency' ) ? $order->get_currency() : ( method_exists( $order, 'get_order_currency' ) ? $order->get_order_currency() : '' ) ;
318
 
319
  if( !$order_currency ) return;
320
 
121
 
122
  $the_order = new WC_Order( get_the_ID() );
123
  if( $the_order ){
124
+ $order_currency = Deprecated_WC_Functions::get_order_currency( $the_order );
125
 
126
  if( !$order_currency && isset( $_COOKIE[ '_wcml_order_currency' ] ) ){
127
  $order_currency = $_COOKIE[ '_wcml_order_currency' ];
314
  // handle currency in order emails before handled in woocommerce
315
  public function fix_currency_before_order_email($order){
316
 
317
+ $order_currency = Deprecated_WC_Functions::get_order_currency( $order );
318
 
319
  if( !$order_currency ) return;
320
 
inc/currencies/class-wcml-multi-currency.php CHANGED
@@ -66,6 +66,15 @@ class WCML_Multi_Currency{
66
  */
67
  public $woocommerce_wpml;
68
 
 
 
 
 
 
 
 
 
 
69
  public function __construct(){
70
  global $woocommerce_wpml;
71
 
@@ -87,6 +96,8 @@ class WCML_Multi_Currency{
87
  $this->custom_prices = new WCML_Custom_Prices( $woocommerce_wpml );
88
  $this->currency_switcher = new WCML_Currency_Switcher;
89
 
 
 
90
  if( defined('W3TC') ){
91
  $this->W3TC = new WCML_W3TC_Multi_Currency();
92
  }
@@ -100,6 +111,7 @@ class WCML_Multi_Currency{
100
  add_action('wp_ajax_nopriv_wcml_switch_currency', array($this, 'switch_currency'));
101
  add_action('wp_ajax_wcml_switch_currency', array($this, 'switch_currency'));
102
  }
 
103
  }
104
 
105
  private function _load_filters(){
@@ -329,11 +341,11 @@ class WCML_Multi_Currency{
329
  $this->woocommerce_wpml->settings['display_custom_prices'] ){
330
 
331
  $product_obj = wc_get_product();
332
- $current_product_id = $product_obj->id;
333
  $original_product_language = $this->woocommerce_wpml->products->get_original_product_language( $current_product_id );
334
  $default = false;
335
 
336
- if( $product_obj->is_type( 'variable' ) ){
337
  foreach( $product_obj->get_children() as $child ){
338
  if( !get_post_meta( apply_filters( 'translate_object_id', $child , get_post_type( $child ), true, $original_product_language ), '_wcml_custom_prices_status', true ) ){
339
  $default = true;
@@ -351,14 +363,23 @@ class WCML_Multi_Currency{
351
  }
352
 
353
  if( isset($_GET['pay_for_order']) && $_GET['pay_for_order'] == true && isset($_GET['key']) ){
354
- $order_id = $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_order_key' AND meta_value = %s", $_GET['key']));
355
  if( $order_id ){
356
  $this->client_currency = get_post_meta( $order_id, '_order_currency', true );
357
  }
358
  }
359
 
360
-
361
- if(isset($_POST['action']) && $_POST['action'] == 'wcml_switch_currency' && !empty($_POST['currency'])){
 
 
 
 
 
 
 
 
 
362
  $this->client_currency = filter_input( INPUT_POST, 'currency', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
363
  }
364
 
@@ -443,6 +464,13 @@ class WCML_Multi_Currency{
443
  }
444
 
445
  $currency = filter_input( INPUT_POST, 'currency', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
 
 
 
 
 
 
 
446
 
447
  $this->set_client_currency($currency);
448
 
@@ -454,7 +482,8 @@ class WCML_Multi_Currency{
454
 
455
  do_action('wcml_switch_currency', $currency );
456
 
457
- exit;
 
458
 
459
  }
460
 
66
  */
67
  public $woocommerce_wpml;
68
 
69
+ /**
70
+ * @var WCML_Exchange_Rate_Service
71
+ */
72
+ public $exchange_rate_services;
73
+
74
+
75
+ /**
76
+ * WCML_Multi_Currency constructor.
77
+ */
78
  public function __construct(){
79
  global $woocommerce_wpml;
80
 
96
  $this->custom_prices = new WCML_Custom_Prices( $woocommerce_wpml );
97
  $this->currency_switcher = new WCML_Currency_Switcher;
98
 
99
+ $this->exchange_rate_services = new WCML_Exchange_Rates( $this->woocommerce_wpml );
100
+
101
  if( defined('W3TC') ){
102
  $this->W3TC = new WCML_W3TC_Multi_Currency();
103
  }
111
  add_action('wp_ajax_nopriv_wcml_switch_currency', array($this, 'switch_currency'));
112
  add_action('wp_ajax_wcml_switch_currency', array($this, 'switch_currency'));
113
  }
114
+
115
  }
116
 
117
  private function _load_filters(){
341
  $this->woocommerce_wpml->settings['display_custom_prices'] ){
342
 
343
  $product_obj = wc_get_product();
344
+ $current_product_id = get_post()->ID;
345
  $original_product_language = $this->woocommerce_wpml->products->get_original_product_language( $current_product_id );
346
  $default = false;
347
 
348
+ if( Deprecated_WC_Functions::get_product_type ($current_product_id ) === 'variable' ){
349
  foreach( $product_obj->get_children() as $child ){
350
  if( !get_post_meta( apply_filters( 'translate_object_id', $child , get_post_type( $child ), true, $original_product_language ), '_wcml_custom_prices_status', true ) ){
351
  $default = true;
363
  }
364
 
365
  if( isset($_GET['pay_for_order']) && $_GET['pay_for_order'] == true && isset($_GET['key']) ){
366
+ $order_id = $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_order_key' AND meta_value = %s", sanitize_text_field( $_GET['key'] ) ) );
367
  if( $order_id ){
368
  $this->client_currency = get_post_meta( $order_id, '_order_currency', true );
369
  }
370
  }
371
 
372
+ if(
373
+ isset( $_POST[ 'action' ] ) &&
374
+ $_POST[ 'action' ] == 'wcml_switch_currency' &&
375
+ !empty( $_POST[ 'currency' ] ) &&
376
+ isset( $_POST[ 'force_switch' ] ) &&
377
+ !$_POST[ 'force_switch' ] &&
378
+ (
379
+ $this->woocommerce_wpml->settings[ 'cart_sync' ][ 'currency_switch' ] == WCML_CART_SYNC ||
380
+ $this->woocommerce_wpml->settings[ 'cart_sync' ][ 'currency_switch' ] == WCML_CART_SYNC
381
+ )
382
+ ){
383
  $this->client_currency = filter_input( INPUT_POST, 'currency', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
384
  }
385
 
464
  }
465
 
466
  $currency = filter_input( INPUT_POST, 'currency', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
467
+ $force_switch = filter_input( INPUT_POST, 'force_switch', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
468
+
469
+ do_action( 'wcml_before_switch_currency', $currency, $force_switch );
470
+
471
+ if( !$force_switch && apply_filters( 'wcml_switch_currency_exception', false, $this->client_currency, $currency ) ){
472
+ die();
473
+ }
474
 
475
  $this->set_client_currency($currency);
476
 
482
 
483
  do_action('wcml_switch_currency', $currency );
484
 
485
+ echo json_encode( array() );
486
+ die();
487
 
488
  }
489
 
inc/currencies/exchange-rate-services/class-wcml-exchange-rates-currencylayer.php ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WCML_Exchange_Rates_Currencylayer extends WCML_Exchange_Rate_Service{
4
+
5
+ private $id = 'currencylayer';
6
+ private $name = 'currencylayer';
7
+ private $url = 'https://currencylayer.com/';
8
+ private $api_url = 'http://apilayer.net/api/live?access_key=%s&source=%s&currencies=%s&amount=1';
9
+
10
+ protected $api_key = '';
11
+ protected $requires_key = true;
12
+
13
+ const REQUIRES_KEY = true;
14
+
15
+ function __construct() {
16
+ parent::__construct( $this->id, $this->name, $this->api_url, $this->url );
17
+ }
18
+
19
+ /**
20
+ * @param $from string
21
+ * @param $to array
22
+ * @return array
23
+ * @throws Exception
24
+ */
25
+ public function get_rates( $from, $tos ){
26
+
27
+ parent::clear_last_error( );
28
+ $rates = array();
29
+
30
+ $url = sprintf( $this->api_url, $this->api_key, $from, join(',', $tos) );
31
+
32
+ $http = new WP_Http();
33
+ $data = $http->request( $url );
34
+
35
+
36
+ if( is_wp_error( $data ) ){
37
+
38
+ $http_error = join("\n", $data->get_error_messages() );
39
+ parent::save_last_error( $http_error );
40
+ throw new Exception( $http_error );
41
+
42
+ } else {
43
+
44
+ $json = json_decode( $data['body'] );
45
+
46
+ if( empty( $json->success ) ){
47
+ if( !empty( $json->error->info ) ){
48
+ if( strpos( $json->error->info, 'You have not supplied an API Access Key' ) !== false ){
49
+ $error = __('You have entered an incorrect API Access Key', 'woocommerce-multilingual');
50
+ }else{
51
+ $error = $json->error->info;
52
+ }
53
+ } else{
54
+ $error = __( 'Cannot get exchange rates. Connection failed.', 'woocommerce-multilingual' );
55
+ }
56
+ parent::save_last_error( $error );
57
+ throw new Exception( $error );
58
+ } else{
59
+
60
+ if( isset( $json->quotes ) ){
61
+ foreach( $tos as $to ){
62
+ if( isset( $json->quotes->{$from.$to} ) ){
63
+ $rates[$to] = round( $json->quotes->{$from.$to}, 4 );
64
+ }
65
+ }
66
+ }
67
+
68
+ }
69
+ }
70
+
71
+ return $rates;
72
+
73
+ }
74
+
75
+ }
inc/currencies/exchange-rate-services/class-wcml-exchange-rates-fixierio.php ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WCML_Exchange_Rates_Fixierio extends WCML_Exchange_Rate_Service{
4
+
5
+ private $id = 'fixierio';
6
+ private $name = 'Fixer.io';
7
+ private $url = 'http://fixer.io/';
8
+ private $api_url = 'http://api.fixer.io/latest?base=%s&symbols=%s';
9
+
10
+ protected $api_key = '';
11
+ const REQUIRES_KEY = false;
12
+
13
+ function __construct() {
14
+ parent::__construct( $this->id, $this->name, $this->api_url, $this->url );
15
+ }
16
+
17
+ /**
18
+ * @param $from string
19
+ * @param $to array
20
+ * @return array
21
+ * @throws Exception
22
+ */
23
+ public function get_rates( $from, $tos ){
24
+
25
+ parent::clear_last_error( );
26
+ $rates = array();
27
+
28
+ $url = sprintf( $this->api_url, $from, join(',', $tos) );
29
+
30
+ $http = new WP_Http();
31
+ $data = $http->request( $url );
32
+
33
+ if( is_wp_error( $data ) ){
34
+
35
+ $http_error = join("\n", $data->get_error_messages() );
36
+ parent::save_last_error( $http_error );
37
+ throw new Exception( $http_error );
38
+
39
+ } else {
40
+
41
+ $json = json_decode( $data['body'] );
42
+
43
+ if( isset( $json->base ) && isset( $json->rates ) ){
44
+ foreach( $json->rates as $to => $rate ){
45
+ $rates[$to] = round( $rate, 4 );
46
+ }
47
+ } else{
48
+ $error = isset( $json->error ) ? $json->error :
49
+ __( 'Cannot get exchange rates. Connection failed.', 'woocommerce-multilingual' );
50
+ parent::save_last_error( $error );
51
+ throw new Exception( $error );
52
+ }
53
+
54
+ }
55
+
56
+ return $rates;
57
+
58
+ }
59
+
60
+ }
inc/currencies/exchange-rate-services/class-wcml-exchange-rates-yahoo-finance.php ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WCML_Exchange_Rates_YahooFinance extends WCML_Exchange_Rate_Service{
4
+
5
+ private $id = 'yahoo';
6
+ private $name = 'Yahoo! Finance';
7
+ private $url = 'https://finance.yahoo.com/currency-converter';
8
+ private $api_url = 'http://finance.yahoo.com/d/quotes.csv?e=.csv&f=c4l1&s=%s'; // EURUSD=X,GBPUSD=X
9
+
10
+ protected $api_key = '';
11
+ const REQUIRES_KEY = false;
12
+
13
+ function __construct() {
14
+ parent::__construct( $this->id, $this->name, $this->api_url, $this->url );
15
+ }
16
+
17
+ /**
18
+ * @param $from string
19
+ * @param $to array
20
+ * @return array
21
+ * @throws Exception
22
+ */
23
+ public function get_rates( $from, $tos ){
24
+
25
+ parent::clear_last_error();
26
+ $rates = array();
27
+
28
+ $pairs = array();
29
+ foreach( $tos as $to ){
30
+ $pairs[] = $from . $to . '=X';
31
+ }
32
+
33
+ $url = sprintf( $this->api_url, join(',', $pairs) );
34
+
35
+ $http = new WP_Http();
36
+ $data = $http->request( $url );
37
+
38
+ if( is_wp_error( $data ) ){
39
+
40
+ $http_error = join("\n", $data->get_error_messages() );
41
+ parent::save_last_error( $http_error );
42
+ throw new Exception( $http_error );
43
+
44
+ } else {
45
+
46
+ // str_getcsv not working as expected
47
+ $lines = explode("\n", trim( $data['body'] ) );
48
+ foreach( $lines as $k => $line ){
49
+
50
+ // Exception: sometimes it returns N/A
51
+ if( substr( $line, 0, 3) === 'N/A' ){
52
+ $to = array_values( $tos )[$k];
53
+ $rate = trim( substr( $line, 4 ) );
54
+ }else{
55
+ $to = substr( $line, 1, 3);
56
+ $rate = trim( substr( $line, 6 ) );
57
+ }
58
+
59
+ if( !is_numeric( $rate ) ){
60
+ $error = sprintf( __("Error reading the exchange rate for %s. Please try again. If the error persist, try selecting a different exchange rate service.", 'woocommerce-multilingual' ), $to );
61
+ parent::save_last_error( $error );
62
+ throw new Exception( $error );
63
+ }
64
+
65
+ $rates[$to] = $rate;
66
+ }
67
+
68
+ }
69
+
70
+ return $rates;
71
+
72
+ }
73
+
74
+ }
inc/deprecated-WC-functions.php ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Deprecated_WC_Functions{
4
+
5
+ public static function is_deprecated(){
6
+
7
+ if( version_compare( WC_VERSION , '2.7', '<' ) ){
8
+ return true;
9
+ }else{
10
+ return false;
11
+ }
12
+
13
+ }
14
+
15
+ public static function get_product_id( $product ){
16
+ if( self::is_deprecated() ){
17
+ return $product->id;
18
+ }else{
19
+ return $product->get_id();
20
+ }
21
+ }
22
+
23
+ public static function get_product_type( $product_id ){
24
+ if( self::is_deprecated() ){
25
+ $product = wc_get_product( $product_id );
26
+ return $product->product_type;
27
+ }else{
28
+ return WC_Product_Factory::get_product_type( $product_id );
29
+ }
30
+ }
31
+
32
+ public static function reduce_stock( $product_id, $qty ){
33
+ if( self::is_deprecated() ){
34
+ $product = wc_get_product( $product_id );
35
+ return $product->reduce_stock( $qty );
36
+ }else{
37
+ return wc_update_product_stock( $product_id, $qty, 'decrease' );
38
+ }
39
+ }
40
+
41
+ public static function increase_stock( $product_id, $qty ){
42
+ if( self::is_deprecated() ){
43
+ $product = wc_get_product( $product_id );
44
+ return $product->increase_stock( $qty );
45
+ }else{
46
+ return wc_update_product_stock( $product_id, $qty, 'increase' );
47
+ }
48
+ }
49
+
50
+ public static function set_stock( $product_id, $qty ){
51
+ if( self::is_deprecated() ){
52
+ $product = wc_get_product( $product_id );
53
+ return $product->set_stock( $qty );
54
+ }else{
55
+ return wc_update_product_stock( $product_id, $qty, 'set' );
56
+ }
57
+ }
58
+
59
+ public static function get_order_currency( $order ){
60
+ if( self::is_deprecated() ){
61
+ return $order->get_order_currency();
62
+ }else{
63
+ return $order->get_currency();
64
+ }
65
+ }
66
+
67
+ }
68
+
69
+ ?>
inc/template-classes/class-wcml-pointer-ui.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WCML_Pointer_UI extends WPML_Templates_Factory {
4
+
5
+ private $content;
6
+ private $doc_link;
7
+ private $selector;
8
+ private $insert_method;
9
+
10
+ function __construct( $content, $doc_link, $insert_after_selector_id = false, $insert_method = false ){
11
+ parent::__construct();
12
+
13
+ $this->content = $content;
14
+ $this->doc_link = $doc_link;
15
+ $this->selector = $insert_after_selector_id;
16
+ $this->insert_method = $insert_method;
17
+
18
+ }
19
+
20
+ public function get_model(){
21
+
22
+ $model = array(
23
+ 'pointer' => md5( rand( 0, 100 ) ),
24
+ 'description' => array(
25
+ 'content' => $this->content,
26
+ 'trnsl_title' => __( 'How to translate this?', 'woocommerce-multilingual' ),
27
+ 'doc_link' => $this->doc_link,
28
+ 'doc_link_text' => __( 'Learn more', 'woocommerce-multilingual' ),
29
+ ),
30
+ 'selector' => $this->selector,
31
+ 'insert_method' => $this->insert_method
32
+ );
33
+
34
+ return $model;
35
+
36
+ }
37
+
38
+ protected function init_template_base_dir() {
39
+ $this->template_paths = array(
40
+ WCML_PLUGIN_PATH . '/templates/',
41
+ );
42
+ }
43
+
44
+ public function get_template() {
45
+ return 'pointer-ui.twig';
46
+ }
47
+
48
+
49
+ }
inc/template-classes/class-wcml-products-ui.php CHANGED
@@ -148,7 +148,7 @@ class WCML_Products_UI extends WPML_Templates_Factory {
148
  $products[ $key ]->edit_post_link = get_edit_post_link( $product->ID );
149
 
150
  if( has_post_thumbnail( $product->ID ) ){
151
- $products[ $key ]->post_thumbnail = get_the_post_thumbnail_url( $product->ID, 150 );
152
  }else{
153
  $products[ $key ]->post_thumbnail = wc_placeholder_img_src();
154
  }
@@ -187,7 +187,7 @@ class WCML_Products_UI extends WPML_Templates_Factory {
187
  $products[ $key ]->categories_list = $this->get_categories_list( $product->ID, $this->get_cat_url() );
188
 
189
  $prod = wc_get_product( $product->ID );
190
- $products[ $key ]->icon_class = $prod->product_type;
191
 
192
  if ( $prod->is_virtual() ) {
193
  $products[ $key ]->icon_class = 'virtual';
148
  $products[ $key ]->edit_post_link = get_edit_post_link( $product->ID );
149
 
150
  if( has_post_thumbnail( $product->ID ) ){
151
+ $products[ $key ]->post_thumbnail = get_the_post_thumbnail_url( $product->ID, array( 150, 150 ) );
152
  }else{
153
  $products[ $key ]->post_thumbnail = wc_placeholder_img_src();
154
  }
187
  $products[ $key ]->categories_list = $this->get_categories_list( $product->ID, $this->get_cat_url() );
188
 
189
  $prod = wc_get_product( $product->ID );
190
+ $products[ $key ]->icon_class = Deprecated_WC_Functions::get_product_type( $product->ID );
191
 
192
  if ( $prod->is_virtual() ) {
193
  $products[ $key ]->icon_class = 'virtual';
inc/template-classes/class-wcml-removed-cart-items-ui.php ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WCML_Removed_Cart_Items_UI extends WPML_Templates_Factory {
4
+
5
+ /**
6
+ * @var woocommerce_wpml
7
+ */
8
+ private $woocommerce_wpml;
9
+ /**
10
+ * @var array
11
+ */
12
+ private $args;
13
+ /**
14
+ * @var sitepress
15
+ */
16
+ private $sitepress;
17
+ /**
18
+ * @var woocommerce
19
+ */
20
+ private $woocommerce;
21
+
22
+ function __construct( &$args, &$woocommerce_wpml, &$sitepress, $woocommerce ){
23
+
24
+ $this->woocommerce_wpml =& $woocommerce_wpml;
25
+ $this->args = $args;
26
+ $this->sitepress = $sitepress;
27
+ $this->woocommerce = $woocommerce;
28
+
29
+ parent::__construct();
30
+ }
31
+
32
+ public function get_model(){
33
+
34
+ $language_details = $this->sitepress->get_language_details( $this->sitepress->get_current_language() );
35
+ $switched_to = $this->woocommerce->session->get( 'wcml_switched_type' ) == 'currency' ? $this->woocommerce_wpml->multi_currency->get_client_currency() : $language_details[ 'display_name' ];
36
+
37
+ $model = array(
38
+ 'products' => $this->get_removed_products(),
39
+ 'title' => sprintf( __( 'Products removed after switching to %s:', 'woocommerce-multilingual'), $switched_to ),
40
+ 'clear' => __( 'Clear list', 'woocommerce-multilingual'),
41
+ 'nonce' => wp_create_nonce( 'wcml_clear_removed_items' ),
42
+ );
43
+
44
+ return $model;
45
+ }
46
+
47
+ public function get_removed_products(){
48
+
49
+ $current_language = $this->sitepress->get_current_language();
50
+ $removed_products_from_session = maybe_unserialize( $this->woocommerce->session->get( 'wcml_removed_items' ) );
51
+ $removed_products = array();
52
+ $removed_product_ids = array();
53
+
54
+ if( is_array( $removed_products_from_session ) ){
55
+ foreach( $removed_products_from_session as $key => $product_id ){
56
+ $tr_product_id = apply_filters( 'translate_object_id', $product_id, 'product', false, $current_language );
57
+
58
+ if( !is_null( $tr_product_id ) && !in_array( $tr_product_id, $removed_product_ids ) ){
59
+ $removed_products[ $key ][ 'id' ] = $removed_product_ids[] = $tr_product_id;
60
+ $removed_products[ $key ][ 'url' ] = get_post_permalink( $tr_product_id );
61
+ $removed_products[ $key ][ 'title' ] = get_post( $tr_product_id )->post_title;
62
+ }
63
+ }
64
+ }
65
+
66
+ return $removed_products;
67
+
68
+ }
69
+
70
+ public function render(){
71
+ echo $this->get_view();
72
+ }
73
+
74
+ protected function init_template_base_dir() {
75
+ $this->template_paths = array(
76
+ WCML_PLUGIN_PATH . '/templates/',
77
+ );
78
+ }
79
+
80
+ public function get_template() {
81
+ return 'removed-cart-items.twig';
82
+ }
83
+
84
+
85
+
86
+ }
inc/template-classes/class-wcml-settings-ui.php CHANGED
@@ -27,7 +27,7 @@ class WCML_Settings_UI extends WPML_Templates_Factory {
27
  'label' => __('WPML Translation Editor', 'woocommerce-multilingual'),
28
 
29
  ),
30
- 'native' => array(
31
  'label' => __('Native WooCommerce product editing screen' , 'woocommerce-multilingual'),
32
 
33
  ),
@@ -36,7 +36,7 @@ class WCML_Settings_UI extends WPML_Templates_Factory {
36
  ),
37
 
38
  'synchronization' => array(
39
- 'heading' => __('Products synchronization', 'woocommerce-multilingual'),
40
  'tip' => __( 'Configure specific product properties that should be synced to translations.', 'woocommerce-multilingual' ),
41
  'sync_date' => array(
42
  'value' => $this->woocommerce_wpml->settings['products_sync_date'],
@@ -49,14 +49,34 @@ class WCML_Settings_UI extends WPML_Templates_Factory {
49
  ),
50
 
51
  'file_sync' => array(
52
- 'heading' => __('Products Download Files', 'woocommerce-multilingual'),
53
- 'tip' => __( 'If you are using downloadable products, you can choose to have their paths
54
  synchronized, or seperate for each language.', 'woocommerce-multilingual' ),
55
  'value' => $this->woocommerce_wpml->settings['file_path_sync'],
56
  'label_same' => __('Use the same files for translations', 'woocommerce-multilingual'),
57
  'label_diff' => __('Add separate download files for translations', 'woocommerce-multilingual'),
58
  ),
59
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
 
61
  'nonce' => wp_nonce_field('wcml_save_settings_nonce', 'wcml_nonce', true, false),
62
  'save_label' => __( 'Save changes', 'woocommerce-multilingual' ),
@@ -66,6 +86,9 @@ class WCML_Settings_UI extends WPML_Templates_Factory {
66
  'native_translation' => WCML_TRANSLATION_METHOD_MANUAL,
67
  'wpml_translation' => WCML_TRANSLATION_METHOD_EDITOR,
68
 
 
 
 
69
  'troubleshooting' => array(
70
  'url' => admin_url( 'admin.php?page=wpml-wcml&tab=troubleshooting' ),
71
  'label' => __( 'Troubleshooting page', 'woocommerce-multilingual' )
27
  'label' => __('WPML Translation Editor', 'woocommerce-multilingual'),
28
 
29
  ),
30
+ 'native' => array(
31
  'label' => __('Native WooCommerce product editing screen' , 'woocommerce-multilingual'),
32
 
33
  ),
36
  ),
37
 
38
  'synchronization' => array(
39
+ 'heading' => __('Products Synchronization', 'woocommerce-multilingual'),
40
  'tip' => __( 'Configure specific product properties that should be synced to translations.', 'woocommerce-multilingual' ),
41
  'sync_date' => array(
42
  'value' => $this->woocommerce_wpml->settings['products_sync_date'],
49
  ),
50
 
51
  'file_sync' => array(
52
+ 'heading' => __('Products Download Files', 'woocommerce-multilingual'),
53
+ 'tip' => __( 'If you are using downloadable products, you can choose to have their paths
54
  synchronized, or seperate for each language.', 'woocommerce-multilingual' ),
55
  'value' => $this->woocommerce_wpml->settings['file_path_sync'],
56
  'label_same' => __('Use the same files for translations', 'woocommerce-multilingual'),
57
  'label_diff' => __('Add separate download files for translations', 'woocommerce-multilingual'),
58
  ),
59
 
60
+ 'cart_sync' => array(
61
+ 'tip' => __('You can choose to clear the cart contents when you change language or currency in case you have problems in cart or checkout page', 'woocommerce-multilingual'),
62
+ 'heading' => __('Cart', 'woocommerce-multilingual'),
63
+ 'lang_switch' => array(
64
+ 'heading' => __('Switching languages when there are items in the cart', 'woocommerce-multilingual'),
65
+ 'sync_label' => __('Synchronize cart content when switching languages', 'woocommerce-multilingual'),
66
+ 'clear_label' => __('Prompt for a confirmation and reset the cart', 'woocommerce-multilingual'),
67
+ 'value' => $this->woocommerce_wpml->settings['cart_sync']['lang_switch']
68
+ ),
69
+ 'currency_switch' => array(
70
+ 'heading' => __('Switching currencies when there are items in the cart', 'woocommerce-multilingual'),
71
+ 'sync_label' => __('Synchronize cart content when switching currencies', 'woocommerce-multilingual'),
72
+ 'clear_label' => __('Prompt for a confirmation and reset the cart', 'woocommerce-multilingual'),
73
+ 'value' => $this->woocommerce_wpml->settings['cart_sync']['currency_switch']
74
+ ),
75
+ 'doc_link' => sprintf( __( 'Not sure which option to choose? Read about %spotential issues when switching languages and currencies while the cart has items%s.',
76
+ 'woocommerce-multilingual' ),
77
+ '<a href="https://wpml.org/documentation/related-projects/woocommerce-multilingual/clearing-cart-contents-when-language-or-currency-change/" target="_blank">', '</a>'
78
+ ),
79
+ ),
80
 
81
  'nonce' => wp_nonce_field('wcml_save_settings_nonce', 'wcml_nonce', true, false),
82
  'save_label' => __( 'Save changes', 'woocommerce-multilingual' ),
86
  'native_translation' => WCML_TRANSLATION_METHOD_MANUAL,
87
  'wpml_translation' => WCML_TRANSLATION_METHOD_EDITOR,
88
 
89
+ 'wcml_cart_sync' => WCML_CART_SYNC,
90
+ 'wcml_cart_clear' => WCML_CART_CLEAR,
91
+
92
  'troubleshooting' => array(
93
  'url' => admin_url( 'admin.php?page=wpml-wcml&tab=troubleshooting' ),
94
  'label' => __( 'Troubleshooting page', 'woocommerce-multilingual' )
inc/template-classes/multi-currency/class-wcml-currency-switcher-ui.php CHANGED
@@ -56,6 +56,7 @@ class WCML_Currency_Switcher_UI extends WPML_Templates_Factory {
56
  }
57
  $wcml_settings = $this->woocommerce_wpml->get_settings();
58
  $multi_currency =& $this->woocommerce_wpml->multi_currency;
 
59
 
60
  if( preg_match( '#%subtotal%#', $format ) ) { // include cart total
61
  if( !is_admin() ){
@@ -103,7 +104,7 @@ class WCML_Currency_Switcher_UI extends WPML_Templates_Factory {
103
  ), $format );
104
 
105
  if( preg_match( '#%subtotal%#', $format ) && !is_admin() ) { // include cart total
106
- $multi_currency->set_client_currency( $multi_currency->get_client_currency() );
107
  }
108
 
109
  return $currency_format;
56
  }
57
  $wcml_settings = $this->woocommerce_wpml->get_settings();
58
  $multi_currency =& $this->woocommerce_wpml->multi_currency;
59
+ $client_currency = $multi_currency->get_client_currency();
60
 
61
  if( preg_match( '#%subtotal%#', $format ) ) { // include cart total
62
  if( !is_admin() ){
104
  ), $format );
105
 
106
  if( preg_match( '#%subtotal%#', $format ) && !is_admin() ) { // include cart total
107
+ $multi_currency->set_client_currency( $client_currency );
108
  }
109
 
110
  return $currency_format;
inc/template-classes/multi-currency/class-wcml-custom-currency-options.php CHANGED
@@ -24,6 +24,17 @@ class WCML_Custom_Currency_Options extends WPML_Templates_Factory {
24
  array_keys( $this->args['currencies'] ), array( $this->args['default_currency'] ) );
25
  $current_currency = empty($this->args['currency_code']) ? current( $currencies_not_used ) : $this->args['currency_code'];
26
 
 
 
 
 
 
 
 
 
 
 
 
27
  $model = array(
28
 
29
  'args' => $this->args,
@@ -34,7 +45,9 @@ class WCML_Custom_Currency_Options extends WPML_Templates_Factory {
34
  'only_numeric' => __( 'Only numeric', 'woocommerce-multilingual' ),
35
  'set_on' => empty($this->args['currency']['updated'] ) ? '' :
36
  sprintf( __( 'Set on %s', 'woocommerce-multilingual' ),
37
- date( 'F j, Y, H:i', strtotime( $this->args['currency']['updated'] ) ) )
 
 
38
  ),
39
  'preview' => array(
40
  'label' => __( 'Currency Preview', 'woocommerce-multilingual' ),
@@ -84,11 +97,9 @@ class WCML_Custom_Currency_Options extends WPML_Templates_Factory {
84
 
85
  ),
86
 
87
- 'currency_converter_url' => 'https://www.google.com/finance/converter?a=1&from=%s&to=%s',
88
- 'currency_converter_label' => __('Get exchange rates', 'woocommerce-multilingual'),
89
- 'currency_converter_title' => __('Check real-time exchange rates, online, from Google Finance Currency Converter', 'woocommerce-multilingual'),
90
-
91
- 'current_currency' => $current_currency
92
 
93
 
94
  );
24
  array_keys( $this->args['currencies'] ), array( $this->args['default_currency'] ) );
25
  $current_currency = empty($this->args['currency_code']) ? current( $currencies_not_used ) : $this->args['currency_code'];
26
 
27
+ $exchange_rate_services =& $this->woocommerce_wpml->multi_currency->exchange_rate_services;
28
+ $exchange_rates_automatic = $exchange_rate_services->get_setting('automatic');
29
+
30
+ if( !$exchange_rates_automatic ){
31
+ $service_id = $exchange_rate_services->get_setting('service');
32
+ $services = $exchange_rate_services->get_services();
33
+ $exchange_rates_service = $services[$service_id]->get_name();
34
+ } else {
35
+ $exchange_rates_service = '';
36
+ }
37
+
38
  $model = array(
39
 
40
  'args' => $this->args,
45
  'only_numeric' => __( 'Only numeric', 'woocommerce-multilingual' ),
46
  'set_on' => empty($this->args['currency']['updated'] ) ? '' :
47
  sprintf( __( 'Set on %s', 'woocommerce-multilingual' ),
48
+ date( 'F j, Y g:i a', strtotime( $this->args['currency']['updated'] ) ) ),
49
+ 'previous' => empty($this->args['currency']['previous_rate'] ) ? '' :
50
+ ' ' . sprintf( __( '(previous value: %s)', 'woocommerce-multilingual' ), $this->args['currency']['previous_rate'] )
51
  ),
52
  'preview' => array(
53
  'label' => __( 'Currency Preview', 'woocommerce-multilingual' ),
97
 
98
  ),
99
 
100
+ 'automatic_rates' => $exchange_rates_automatic,
101
+ 'automatic_rates_tip' => sprintf( __('Exchange rate updated automatically from %s', 'woocommerce-multilingual' ), $exchange_rates_service ),
102
+ 'current_currency' => $current_currency
 
 
103
 
104
 
105
  );
inc/template-classes/multi-currency/class-wcml-exchange-rates-ui.php ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WCML_Exchange_Rates_UI extends WPML_Templates_Factory {
4
+
5
+ /**
6
+ * @var woocommerce_wpml
7
+ */
8
+ private $woocommerce_wpml;
9
+ /**
10
+ * @var array
11
+ */
12
+ private $services;
13
+ /**
14
+ * @var array
15
+ */
16
+ private $settings;
17
+
18
+ function __construct( $woocommerce_wpml ){
19
+ parent::__construct();
20
+
21
+ $this->woocommerce_wpml =& $woocommerce_wpml;
22
+ $services = $this->woocommerce_wpml->multi_currency->exchange_rate_services->get_services();
23
+ $this->settings = $this->woocommerce_wpml->multi_currency->exchange_rate_services->get_settings();
24
+
25
+ foreach( $services as $id => $service ){
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
+ );
33
+ }
34
+ }
35
+
36
+ public function get_model(){
37
+
38
+ $last_updated = empty( $this->settings['last_updated'] ) ?
39
+ '<i>' . __( 'never', 'woocommerce-multilingual' ) . '</i>' :
40
+ date_i18n( 'F j, Y g:i a', $this->settings['last_updated'] );
41
+
42
+ $model = array(
43
+ 'strings' => array(
44
+
45
+ 'header' => __( 'Automatic Exchange Rates', 'woocommerce-multilingual' ),
46
+ 'no_currencies' => __( "You haven't added any secondary currencies.", 'woocommerce-multilingual' ),
47
+ 'enable_automatic' => __( 'Enable automatic exchange rates', 'woocommerce-multilingual' ),
48
+ 'services_label' => __( 'Exchange rates source', 'woocommerce-multilingual' ),
49
+ 'lifting_label' => __( 'Lifting charge', 'woocommerce-multilingual' ),
50
+ 'lifting_details1' => __( 'The lifting charge adjusts the exchange rate provided by the selected service before it is saved. The exchange rates displayed in the table above include the lifting charge.', 'woocommerce-multilingual' ),
51
+ 'lifting_details2' => __( 'Exchange rate = %s exchange rate x (1 + lifting charge / 100)', 'woocommerce-multilingual' ),
52
+ 'services_api' => __( 'API key (required)', 'woocommerce-multilingual' ),
53
+ 'frequency' => __( 'Update frequency', 'woocommerce-multilingual' ),
54
+ 'update' => __( 'Update manually now', 'woocommerce-multilingual' ),
55
+ 'update_tip' => __( 'You have to save all settings before updating exchange rates', 'woocommerce-multilingual' ),
56
+ 'manually' => __( 'Manually', 'woocommerce-multilingual'),
57
+ 'daily' => __( 'Daily', 'woocommerce-multilingual' ),
58
+ 'weekly' => __( 'Weekly on', 'woocommerce-multilingual' ),
59
+ 'monthly' => __( 'Monthly on the', 'woocommerce-multilingual' ),
60
+ 'key_placeholder' => __( 'Enter API key', 'woocommerce-multilingual' ),
61
+ 'key_required' => __( 'API key (required)', 'woocommerce-multilingual' ),
62
+ 'nonce' => wp_create_nonce( 'update-exchange-rates' ),
63
+ 'updated_time' => sprintf(
64
+ __('Last updated: %s', 'woocommerce-multilingual' ),
65
+ '<span class="time">' . $last_updated . '</span>'
66
+ ),
67
+ 'updated_success' => __( 'Exchange rates updated successfully', 'woocommerce-multilingual' ),
68
+ 'visit_website' => __( 'Visit website', 'woocommerce-multilingual' )
69
+
70
+ ),
71
+
72
+ 'services' => $this->services,
73
+ 'settings' => $this->settings,
74
+
75
+ 'secondary_currencies' => $this->woocommerce_wpml->multi_currency->get_currencies(),
76
+
77
+ );
78
+
79
+ return $model;
80
+ }
81
+
82
+ protected function init_template_base_dir() {
83
+ $this->template_paths = array(
84
+ WCML_PLUGIN_PATH . '/templates/multi-currency/',
85
+ );
86
+ }
87
+
88
+ public function get_template() {
89
+ return 'exchange-rates.twig';
90
+ }
91
+
92
+ }
inc/template-classes/multi-currency/class-wcml-multi-currency-ui.php CHANGED
@@ -27,12 +27,12 @@ class WCML_Multi_Currency_UI extends WPML_Templates_Factory {
27
 
28
  $functions = array(
29
  new Twig_SimpleFunction( 'get_flag_url', array( $this, 'get_flag_url' ) ),
30
- new Twig_SimpleFunction( 'get_rate', array( $this, 'get_rate' ) ),
31
  new Twig_SimpleFunction( 'is_currency_on', array( $this, 'is_currency_on' ) ),
32
  new Twig_SimpleFunction( 'get_language_currency', array( $this, 'get_language_currency' ) ),
33
  new Twig_SimpleFunction( 'get_currency_symbol', array( $this, 'get_currency_symbol' ) ),
34
  new Twig_SimpleFunction( 'get_currency_name', array( $this, 'get_currency_name' ) ),
35
- new Twig_SimpleFunction( 'wp_do_action', array( $this, 'wp_do_action' ) )
 
36
  );
37
 
38
  parent::__construct( $functions );
@@ -54,6 +54,7 @@ class WCML_Multi_Currency_UI extends WPML_Templates_Factory {
54
  $currencies_positions[$code] = $this->price_position_format( $currency['position'], $code );
55
  }
56
 
 
57
 
58
  $model = array(
59
  'strings' => array(
@@ -149,7 +150,8 @@ class WCML_Multi_Currency_UI extends WPML_Templates_Factory {
149
  'visibility_label' => __('Show a currency selector on the product page template', 'woocommerce-multilingual'),
150
  'visibility_on' => isset($this->woocommerce_wpml->settings['currency_switcher_product_visibility']) ?
151
  $this->woocommerce_wpml->settings['currency_switcher_product_visibility']:1
152
- )
 
153
  );
154
 
155
  return $model;
@@ -216,10 +218,6 @@ class WCML_Multi_Currency_UI extends WPML_Templates_Factory {
216
  return $this->sitepress->get_flag_url( $code );
217
  }
218
 
219
- public function get_rate($wc_currency, $rate, $code){
220
- return sprintf( '1 %s = %s %s', $wc_currency, $rate, $code );
221
- }
222
-
223
  public function is_currency_on($currency, $language) {
224
  return $this->woocommerce_wpml->settings['currency_options'][ $currency ]['languages'][ $language ];
225
  }
@@ -282,4 +280,10 @@ class WCML_Multi_Currency_UI extends WPML_Templates_Factory {
282
  do_action( $hook );
283
  }
284
 
 
 
 
 
 
 
285
  }
27
 
28
  $functions = array(
29
  new Twig_SimpleFunction( 'get_flag_url', array( $this, 'get_flag_url' ) ),
 
30
  new Twig_SimpleFunction( 'is_currency_on', array( $this, 'is_currency_on' ) ),
31
  new Twig_SimpleFunction( 'get_language_currency', array( $this, 'get_language_currency' ) ),
32
  new Twig_SimpleFunction( 'get_currency_symbol', array( $this, 'get_currency_symbol' ) ),
33
  new Twig_SimpleFunction( 'get_currency_name', array( $this, 'get_currency_name' ) ),
34
+ new Twig_SimpleFunction( 'wp_do_action', array( $this, 'wp_do_action' ) ),
35
+ new Twig_SimpleFunction( 'get_weekday', array( $this, 'get_weekday' ) )
36
  );
37
 
38
  parent::__construct( $functions );
54
  $currencies_positions[$code] = $this->price_position_format( $currency['position'], $code );
55
  }
56
 
57
+ $exchange_rates_ui = new WCML_Exchange_Rates_UI( $this->woocommerce_wpml );
58
 
59
  $model = array(
60
  'strings' => array(
150
  'visibility_label' => __('Show a currency selector on the product page template', 'woocommerce-multilingual'),
151
  'visibility_on' => isset($this->woocommerce_wpml->settings['currency_switcher_product_visibility']) ?
152
  $this->woocommerce_wpml->settings['currency_switcher_product_visibility']:1
153
+ ),
154
+ 'exchange_rates' => $exchange_rates_ui->get_model()
155
  );
156
 
157
  return $model;
218
  return $this->sitepress->get_flag_url( $code );
219
  }
220
 
 
 
 
 
221
  public function is_currency_on($currency, $language) {
222
  return $this->woocommerce_wpml->settings['currency_options'][ $currency ]['languages'][ $language ];
223
  }
280
  do_action( $hook );
281
  }
282
 
283
+ public function get_weekday( $day_index ){
284
+ global $wp_locale;
285
+ return $wp_locale->get_weekday( $day_index );
286
+ }
287
+
288
+
289
  }
inc/template-classes/status/class-wcml-status-config-warnings-ui.php CHANGED
@@ -34,7 +34,6 @@ class WCML_Status_Config_Warnings_UI extends WPML_Templates_Factory {
34
  'not_en_doc_page' => 'https://wpml.org/?page_id=355545',
35
  'strings' => array(
36
  'conf' => __( 'Configuration Warnings', 'woocommerce-multilingual' ),
37
- 'report' => __( 'Reporting miscelaneous configuration issues that can make WooCommerce Multilingual not run normally', 'woocommerce-multilingual' ),
38
  'base_not_trnsl' => __( 'Your product permalink base is not translated to:', 'woocommerce-multilingual' ),
39
  'trsl_urls' => __( 'Translate URLs', 'woocommerce-multilingual' ),
40
  'def_and_st_not_en' => __( "Your site's default language is not English and the strings language is also not English.", 'woocommerce-multilingual' ),
34
  'not_en_doc_page' => 'https://wpml.org/?page_id=355545',
35
  'strings' => array(
36
  'conf' => __( 'Configuration Warnings', 'woocommerce-multilingual' ),
 
37
  'base_not_trnsl' => __( 'Your product permalink base is not translated to:', 'woocommerce-multilingual' ),
38
  'trsl_urls' => __( 'Translate URLs', 'woocommerce-multilingual' ),
39
  'def_and_st_not_en' => __( "Your site's default language is not English and the strings language is also not English.", 'woocommerce-multilingual' ),
inc/template-classes/status/class-wcml-status-taxonomies-ui.php CHANGED
@@ -19,14 +19,13 @@ class WCML_Status_Taxonomies_UI extends WPML_Templates_Factory {
19
  'run_site' => __( 'To run a fully translated site, you should translate all taxonomy terms. Some store elements, such as variations, depend on taxonomy translation.', 'woocommerce-multilingual' ),
20
  'not_req_trnsl' => __( '%s do not require translation.', 'woocommerce-multilingual' ),
21
  'req_trnsl' => __( 'This taxonomy requires translation.', 'woocommerce-multilingual' ),
22
- 'incl_trnsl' => __( 'Include in translation', 'woocommerce-multilingual' ),
23
  'miss_trnsl_one' => __( '%d %s is missing translations.', 'woocommerce-multilingual' ),
24
  'miss_trnsl_more' => __( '%d %s are missing translations.', 'woocommerce-multilingual' ),
25
  'trnsl' => __( 'Translate %s', 'woocommerce-multilingual' ),
26
  'doesnot_req_trnsl' => __( 'This taxonomy does not require translation.', 'woocommerce-multilingual' ),
27
- 'exclude' => __( 'Exclude from translation', 'woocommerce-multilingual' ),
28
  'all_trnsl' => __( 'All %s are translated.', 'woocommerce-multilingual' ),
29
- 'not_to_trnsl' => __( 'Right now, there are no taxonomy terms needing translation.', 'woocommerce-multilingual' )
 
30
  ),
31
  'nonces' => array(
32
  'ignore_tax' => wp_create_nonce( 'wcml_ingore_taxonomy_translation_nonce' )
@@ -42,12 +41,13 @@ class WCML_Status_Taxonomies_UI extends WPML_Templates_Factory {
42
  $taxonomies_data = array();
43
 
44
  foreach ( $taxonomies as $key => $taxonomy ) {
 
45
  $taxonomies_data[$key]['tax'] = $taxonomy;
46
  $taxonomies_data[$key]['untranslated'] = $this->woocommerce_wpml->terms->get_untranslated_terms_number($taxonomy);
47
  $taxonomies_data[$key]['fully_trans'] = $this->woocommerce_wpml->terms->is_fully_translated($taxonomy);
48
  $taxonomy_object = get_taxonomy($taxonomy);
49
- $taxonomies_data[$key]['name'] = $taxonomy_object->labels->name;
50
- $taxonomies_data[$key]['name_singular'] = $taxonomy_object->labels->singular_name;
51
 
52
  if( substr( $taxonomy, 0, 3 ) == 'pa_' ){
53
  $taxonomies_data[$key]['url'] = admin_url( 'admin.php?page=wpml-wcml&tab=product-attributes&taxonomy=' . $taxonomy );
19
  'run_site' => __( 'To run a fully translated site, you should translate all taxonomy terms. Some store elements, such as variations, depend on taxonomy translation.', 'woocommerce-multilingual' ),
20
  'not_req_trnsl' => __( '%s do not require translation.', 'woocommerce-multilingual' ),
21
  'req_trnsl' => __( 'This taxonomy requires translation.', 'woocommerce-multilingual' ),
 
22
  'miss_trnsl_one' => __( '%d %s is missing translations.', 'woocommerce-multilingual' ),
23
  'miss_trnsl_more' => __( '%d %s are missing translations.', 'woocommerce-multilingual' ),
24
  'trnsl' => __( 'Translate %s', 'woocommerce-multilingual' ),
25
  'doesnot_req_trnsl' => __( 'This taxonomy does not require translation.', 'woocommerce-multilingual' ),
 
26
  'all_trnsl' => __( 'All %s are translated.', 'woocommerce-multilingual' ),
27
+ 'not_to_trnsl' => __( 'Right now, there are no taxonomy terms needing translation.', 'woocommerce-multilingual' ),
28
+ 'conf_warning' => sprintf( __( 'To configure product taxonomies or attributes as translatable or not translatable, go to the %sMultilingual Content Setup%s', 'woocommerce-multilingual' ), '<a href="'.admin_url('admin.php?page=wpml-translation-management%2Fmenu%2Fmain.php&sm=mcsetup#ml-content-setup-sec-8').'">','</a>' )
29
  ),
30
  'nonces' => array(
31
  'ignore_tax' => wp_create_nonce( 'wcml_ingore_taxonomy_translation_nonce' )
41
  $taxonomies_data = array();
42
 
43
  foreach ( $taxonomies as $key => $taxonomy ) {
44
+ if( $taxonomy == 'product_type' ) continue;
45
  $taxonomies_data[$key]['tax'] = $taxonomy;
46
  $taxonomies_data[$key]['untranslated'] = $this->woocommerce_wpml->terms->get_untranslated_terms_number($taxonomy);
47
  $taxonomies_data[$key]['fully_trans'] = $this->woocommerce_wpml->terms->is_fully_translated($taxonomy);
48
  $taxonomy_object = get_taxonomy($taxonomy);
49
+ $taxonomies_data[$key]['name'] = ucfirst( !empty( $taxonomy_object->labels->name ) ? $taxonomy_object->labels->name : $taxonomy_object->labels->singular_name );
50
+ $taxonomies_data[$key]['name_singular'] = ucfirst( $taxonomy_object->labels->singular_name );
51
 
52
  if( substr( $taxonomy, 0, 3 ) == 'pa_' ){
53
  $taxonomies_data[$key]['url'] = admin_url( 'admin.php?page=wpml-wcml&tab=product-attributes&taxonomy=' . $taxonomy );
inc/translation-editor/class-wcml-editor-ui-product-job.php CHANGED
@@ -14,6 +14,8 @@ class WCML_Editor_UI_Product_Job extends WPML_Editor_UI_Job {
14
  private $wpdb;
15
  private $job_details;
16
  private $product;
 
 
17
  private $not_display_fields_for_variables_product;
18
 
19
  function __construct( $job_details, &$woocommerce_wpml, &$sitepress, &$wpdb ) {
@@ -28,6 +30,9 @@ class WCML_Editor_UI_Product_Job extends WPML_Editor_UI_Job {
28
 
29
  $this->job_details = $job_details;
30
  $this->product = wc_get_product( $job_details[ 'job_id' ] );
 
 
 
31
 
32
  $source_lang = $this->sitepress->get_language_for_element( $job_details[ 'job_id' ], 'post_product' );
33
  $target_lang = $job_details[ 'target'];
@@ -37,8 +42,8 @@ class WCML_Editor_UI_Product_Job extends WPML_Editor_UI_Job {
37
  parent::__construct(
38
  $job_details[ 'job_id' ],
39
  'wc_product', __( 'Product', 'woocommerce-multilingual' ),
40
- $this->product->post->post_title,
41
- get_post_permalink( $this->product->id ),
42
  $source_lang,
43
  $target_lang,
44
  $translation_complete,
@@ -54,7 +59,7 @@ class WCML_Editor_UI_Product_Job extends WPML_Editor_UI_Job {
54
 
55
  $translation_complete = false;
56
 
57
- $product_trid = $this->sitepress->get_element_trid( $this->product->id, 'post_product' );
58
  $product_translations = $this->sitepress->get_element_translations( $product_trid, 'post_product', false, false, true );
59
  if ( isset( $this->job_details[ 'translation_complete' ] ) ) {
60
  $translation_complete = $this->job_details[ 'translation_complete' ];
@@ -76,9 +81,9 @@ class WCML_Editor_UI_Product_Job extends WPML_Editor_UI_Job {
76
 
77
  $is_duplicate_product = false;
78
 
79
- $product_trid = $this->sitepress->get_element_trid( $this->product->id, 'post_product' );
80
  $product_translations = $this->sitepress->get_element_translations( $product_trid, 'post_product', false, false, true );
81
- if ( isset( $product_translations[ $this->get_target_language() ] ) && get_post_meta( $product_translations[ $this->get_target_language() ]->element_id, '_icl_lang_duplicate_of', true ) === $this->product->id ) {
82
  $is_duplicate_product = true;
83
  }
84
 
@@ -102,9 +107,9 @@ class WCML_Editor_UI_Product_Job extends WPML_Editor_UI_Job {
102
  /*
103
  * Images
104
  */
105
- $product_images = $this->woocommerce_wpml->media->product_images_ids( $this->product->id );
106
  // Exclude not-duplicated attachments and featured
107
- $product_images = $this->woocommerce_wpml->media->exclude_not_duplicated_attachments( $product_images, $this->product->id );
108
 
109
  if ( count( $product_images ) ) {
110
 
@@ -130,8 +135,8 @@ class WCML_Editor_UI_Product_Job extends WPML_Editor_UI_Job {
130
  $this->add_field( $attributes_section );
131
  }
132
 
133
- $custom_fields = $this->get_product_custom_fields_to_translate( $this->product->id );
134
- if( $this->product->product_type === 'external' ){
135
  $custom_fields = array_diff( $custom_fields, array( '_product_url', '_button_text' ) );
136
  }
137
 
@@ -143,7 +148,7 @@ class WCML_Editor_UI_Product_Job extends WPML_Editor_UI_Job {
143
  $this->add_field( $custom_fields_section );
144
  }
145
 
146
- if( $this->woocommerce_wpml->products->is_variable_product( $this->product->id ) ){
147
  $variations = $this->product->get_available_variations();
148
 
149
  if( !empty( $variations ) ){
@@ -160,11 +165,11 @@ class WCML_Editor_UI_Product_Job extends WPML_Editor_UI_Job {
160
 
161
  if( $this->product->is_downloadable() ){
162
  $is_variable = false;
163
- if( $this->woocommerce_wpml->products->is_variable_product( $this->product->id ) ){
164
  $files_data = $this->get_files_for_variations();
165
  $is_variable = true;
166
  }else{
167
- $files_data = array( $this->product->id => $this->woocommerce_wpml->downloadable->get_files_data( $this->product->id ) );
168
  }
169
 
170
  foreach( $files_data as $post_id => $file_data ){
@@ -199,14 +204,14 @@ class WCML_Editor_UI_Product_Job extends WPML_Editor_UI_Job {
199
  }
200
  }
201
 
202
- if( $this->product->product_type === 'external' ){
203
  $external_product_section = new WPML_Editor_UI_Field_Section( __( 'External Product', 'woocommerce-multilingual' ) );
204
  $external_product_section->add_field( new WPML_Editor_UI_Single_Line_Field( '_product_url', __( 'Product url', 'woocommerce-multilingual' ), $this->data, true ) );
205
  $external_product_section->add_field( new WPML_Editor_UI_Single_Line_Field( '_button_text', __( 'Button text', 'woocommerce-multilingual' ), $this->data, true ) );
206
  $this->add_field( $external_product_section );
207
  }
208
 
209
- do_action( 'wcml_gui_additional_box_html', $this, $this->product->id, $this->data );
210
 
211
  }
212
 
@@ -243,17 +248,17 @@ class WCML_Editor_UI_Product_Job extends WPML_Editor_UI_Job {
243
 
244
  function get_data() {
245
 
246
- $trn_product_id = apply_filters( 'translate_object_id', $this->product->id, 'product', false, $this->get_target_language() );
247
  $translation = false;
248
  if ( null !== $trn_product_id ) {
249
  $translation = get_post( $trn_product_id );
250
  }
251
 
252
- $element_data = array( 'title' => array( 'original' => $this->product->post->post_title ),
253
- 'slug' => array( 'original' => urldecode( $this->product->post->post_name ) ),
254
- 'product_content' => array( 'original' => $this->product->post->post_content ),
255
- 'product_excerpt' => array( 'original' => $this->product->post->post_excerpt ),
256
- '_purchase_note' => array( 'original' => get_post_meta( $this->product->id, '_purchase_note', true ) )
257
  );
258
 
259
  if ( $translation ) {
@@ -264,7 +269,7 @@ class WCML_Editor_UI_Product_Job extends WPML_Editor_UI_Job {
264
  $element_data[ '_purchase_note' ][ 'translation' ] = get_post_meta( $translation->ID, '_purchase_note', true );
265
  }
266
 
267
- $product_images = $this->woocommerce_wpml->media->product_images_ids( $this->product->id );
268
  foreach( $product_images as $image_id ) {
269
  $attachment_data = $this->wpdb->get_row( $this->wpdb->prepare( "SELECT post_title,post_excerpt,post_content FROM {$this->wpdb->posts} WHERE ID = %d", $image_id ) );
270
  if( !$attachment_data ) continue;
@@ -293,16 +298,16 @@ class WCML_Editor_UI_Product_Job extends WPML_Editor_UI_Job {
293
  $element_data[ $attr_key.'_name' ] = array( 'original' => $attribute['name'] );
294
  $element_data[ $attr_key ] = array( 'original' => $attribute['value'] );
295
 
296
- $trn_attribute = $this->woocommerce_wpml->attributes->get_custom_attribute_translation( $this->product->id, $attr_key, $attribute, $this->get_target_language() );
297
 
298
  $element_data[ $attr_key.'_name' ][ 'translation' ] = $trn_attribute['name'] ? $trn_attribute['name'] : '';
299
  $element_data[ $attr_key ][ 'translation' ] = $trn_attribute['value'] ? $trn_attribute['value'] : '';
300
  }
301
  }
302
 
303
- $element_data = $this->add_custom_field_to_element_data( $element_data, $this->product->id, isset( $translation->ID ) ? $translation->ID : false, false );
304
 
305
- if( $this->woocommerce_wpml->products->is_variable_product( $this->product->id ) ){
306
  $variations = $this->product->get_available_variations();
307
 
308
  if( !empty( $variations ) ){
@@ -317,8 +322,8 @@ class WCML_Editor_UI_Product_Job extends WPML_Editor_UI_Job {
317
  }
318
 
319
 
320
- $files_data = array( $this->product->id => $this->woocommerce_wpml->downloadable->get_files_data( $this->product->id ) );
321
- if( $this->woocommerce_wpml->products->is_variable_product( $this->product->id ) ){
322
  $files_data = $this->get_files_for_variations();
323
  }
324
 
@@ -345,7 +350,7 @@ class WCML_Editor_UI_Product_Job extends WPML_Editor_UI_Job {
345
  }
346
  }
347
 
348
- $element_data = apply_filters( 'wcml_gui_additional_box_data', $element_data, $this->product->id, $translation, $this->get_target_language() );
349
 
350
  return $element_data;
351
  }
@@ -391,14 +396,14 @@ class WCML_Editor_UI_Product_Job extends WPML_Editor_UI_Job {
391
 
392
  $return = array();
393
 
394
- if ( $this->product->post->post_type !== 'product' ) {
395
  return $return;
396
  }
397
 
398
  $languages = $this->sitepress->get_active_languages();
399
 
400
- $product_trid = $this->sitepress->get_element_trid( $this->product->id, 'post_' . $this->product->post->post_type );
401
- $tr_product_id = apply_filters( 'translate_object_id', $this->product->id, 'product', false, $this->get_target_language() );
402
 
403
  new WCML_Editor_Save_Filters( $product_trid, $this->get_target_language() );
404
  if ( get_magic_quotes_gpc() ) {
@@ -414,7 +419,7 @@ class WCML_Editor_UI_Product_Job extends WPML_Editor_UI_Job {
414
  //insert new post
415
  $args = array();
416
  $args[ 'post_title' ] = $translations[ md5( 'title' ) ];
417
- $args[ 'post_type' ] = $this->product->post->post_type;
418
  $args[ 'post_content' ] = $translations[ md5( 'product_content' ) ];
419
  $args[ 'post_excerpt' ] = $translations[ md5( 'product_excerpt' ) ];
420
 
@@ -422,11 +427,11 @@ class WCML_Editor_UI_Product_Job extends WPML_Editor_UI_Job {
422
  return new WP_Error( 'empty_content', __( 'Content, title, and excerpt are empty.' ) );
423
  }
424
 
425
- $args[ 'post_status' ] = $this->product->post->post_status;
426
- $args[ 'menu_order '] = $this->product->post->menu_order;
427
- $args[ 'ping_status' ] = $this->product->post->ping_status;
428
- $args[ 'comment_status' ] = $this->product->post->comment_status;
429
- $product_parent = apply_filters( 'translate_object_id', $this->product->post->post_parent, 'product', false, $this->get_target_language() );
430
  $args['post_parent'] = null === $product_parent ? 0 : $product_parent;
431
 
432
  //TODO: remove after change required WPML version > 3.3
@@ -435,7 +440,7 @@ class WCML_Editor_UI_Product_Job extends WPML_Editor_UI_Job {
435
  $_POST[ 'icl_post_language' ] = $this->get_target_language();
436
 
437
  if ( $this->woocommerce_wpml->settings[ 'products_sync_date' ] ) {
438
- $args[ 'post_date' ] = $this->product->post->post_date;
439
  }
440
 
441
  $tr_product_id = wp_insert_post( $args );
@@ -454,7 +459,7 @@ class WCML_Editor_UI_Product_Job extends WPML_Editor_UI_Job {
454
 
455
  $this->wpdb->update( $this->wpdb->prefix . 'icl_translations', array( 'element_id' => $tr_product_id ), array( 'translation_id' => $translation_id ) );
456
  } else {
457
- $this->sitepress->set_element_language_details( $tr_product_id, 'post_' . $this->product->post->post_type, $product_trid, $this->get_target_language() );
458
  }
459
 
460
  } else {
@@ -464,10 +469,10 @@ class WCML_Editor_UI_Product_Job extends WPML_Editor_UI_Job {
464
  $args[ 'post_title' ] = $translations[ md5( 'title' ) ];
465
  $args[ 'post_content' ] = $translations[ md5( 'product_content' ) ];
466
  $args[ 'post_excerpt' ] = $translations[ md5( 'product_excerpt' ) ];
467
- $args[ 'post_status' ] = $this->product->post->post_status;
468
- $args[ 'ping_status' ] = $this->product->post->ping_status;
469
- $args[ 'comment_status' ] = $this->product->post->comment_status;
470
- $product_parent = apply_filters( 'translate_object_id', $this->product->post->post_parent, 'product', false, $this->get_target_language() );
471
  $args['post_parent'] = null === $product_parent ? 0 : $product_parent;
472
  $_POST[ 'to_lang' ] = $this->get_target_language();
473
 
@@ -483,46 +488,46 @@ class WCML_Editor_UI_Product_Job extends WPML_Editor_UI_Job {
483
  $new_post_name = sanitize_title( $translations[ md5( 'slug' ) ] ? $translations[ md5( 'slug' ) ] : $translations[ md5( 'title' ) ]);
484
  $_POST[ 'new_title' ] = $translations[ md5( 'title' ) ];
485
  $_POST[ 'new_slug' ] = $new_post_name;
486
- $new_slug = wp_unique_post_slug( $new_post_name, $tr_product_id, $this->product->post->post_status, $this->product->post->post_type, $args[ 'post_parent' ] );
487
  $this->wpdb->update( $this->wpdb->posts, array( 'post_name' => $new_slug ), array( 'ID' => $tr_product_id ) );
488
  }
489
 
490
- $this->sitepress->set_element_language_details( $tr_product_id, 'post_' . $this->product->post->post_type, $product_trid, $this->get_target_language() );
491
 
492
  }
493
 
494
  $product_translations = $this->sitepress->get_element_translations( $product_trid , 'post_product', false, false, true );
495
 
496
- do_action( 'wcml_before_sync_product_data', $this->product->id, $tr_product_id, $this->get_target_language() );
497
 
498
- $this->woocommerce_wpml->sync_product_data->duplicate_product_post_meta( $this->product->id, $tr_product_id, $translations );
499
 
500
  //sync taxonomies
501
- $this->woocommerce_wpml->sync_product_data->sync_product_taxonomies( $this->product->id, $tr_product_id, $this->get_target_language() );
502
 
503
- do_action( 'wcml_update_extra_fields', $this->product->id, $tr_product_id, $translations, $this->get_target_language() );
504
 
505
- $this->woocommerce_wpml->attributes->sync_product_attr( $this->product->id, $tr_product_id, $this->get_target_language(), $translations );
506
 
507
- $this->woocommerce_wpml->attributes->sync_default_product_attr( $this->product->id, $tr_product_id, $this->get_target_language() );
508
 
509
  //sync media
510
  if ( $this->woocommerce_wpml->media->settings[ 'duplicate_featured' ] ) {
511
  //sync feature image
512
- $this->woocommerce_wpml->media->sync_thumbnail_id( $this->product->id, $tr_product_id, $this->get_target_language() );
513
  }
514
 
515
  if ( $this->woocommerce_wpml->media->settings[ 'duplicate_media' ] ) {
516
  //sync product gallery
517
- $this->woocommerce_wpml->media->sync_product_gallery( $this->product->id );
518
  }
519
 
520
  // synchronize post variations
521
- $this->woocommerce_wpml->sync_variations_data->sync_product_variations( $this->product->id, $tr_product_id, $this->get_target_language(), $translations );
522
 
523
- $this->woocommerce_wpml->sync_product_data->sync_linked_products( $this->product->id, $tr_product_id, $this->get_target_language() );
524
  //save images texts
525
- $product_images = $this->woocommerce_wpml->media->product_images_ids( $this->product->id );
526
 
527
  if ( $product_images ) {
528
  foreach ( $product_images as $image_id ) {
@@ -558,13 +563,13 @@ class WCML_Editor_UI_Product_Job extends WPML_Editor_UI_Job {
558
  }
559
  ob_start();
560
 
561
- $this->woocommerce_wpml->products->get_translation_statuses( $this->product->id, $product_translations, $languages, isset( $translations['slang'] )
562
  && $translations['slang']
563
  !== 'all' ? $translations['slang'] : false, $product_trid, $this->get_target_language() );
564
  $return[ 'status_link' ] = ob_get_clean();
565
 
566
  // no longer a duplicate
567
- delete_post_meta( $tr_product_id, '_icl_lang_duplicate_of', $this->product->id );
568
 
569
  return $return;
570
 
@@ -572,7 +577,7 @@ class WCML_Editor_UI_Product_Job extends WPML_Editor_UI_Job {
572
 
573
  public function get_custom_product_atributes( )
574
  {
575
- $attributes = get_post_meta( $this->product->id, '_product_attributes', true);
576
  if (!is_array($attributes)) {
577
  $attributes = array();
578
  }
@@ -597,12 +602,12 @@ class WCML_Editor_UI_Product_Job extends WPML_Editor_UI_Job {
597
  return false;
598
  }
599
 
600
- $exception = apply_filters('wcml_product_content_exception', true, $this->product->id, $field);
601
  if ( !$exception ) {
602
  return false;
603
  }
604
 
605
- $custom_key_label = apply_filters('wcml_product_content_label', $field, $this->product->id);
606
  if ( $custom_key_label !== $field ) {
607
  $label = $custom_key_label;
608
  return $label;
@@ -624,7 +629,7 @@ class WCML_Editor_UI_Product_Job extends WPML_Editor_UI_Job {
624
 
625
  global $wpdb;
626
 
627
- $variations = $wpdb->get_results($wpdb->prepare("SELECT * FROM $wpdb->posts WHERE post_parent = %d AND post_type = 'product_variation'", $this->product->id));
628
  $variations_files = array();
629
 
630
  foreach ($variations as $variation) {
14
  private $wpdb;
15
  private $job_details;
16
  private $product;
17
+ private $product_id;
18
+ private $product_type;
19
  private $not_display_fields_for_variables_product;
20
 
21
  function __construct( $job_details, &$woocommerce_wpml, &$sitepress, &$wpdb ) {
30
 
31
  $this->job_details = $job_details;
32
  $this->product = wc_get_product( $job_details[ 'job_id' ] );
33
+ $this->original_post = get_post( $job_details[ 'job_id' ] );
34
+ $this->product_id = Deprecated_WC_Functions::get_product_id( $this->product );
35
+ $this->product_type = Deprecated_WC_Functions::get_product_type( $this->product_id );
36
 
37
  $source_lang = $this->sitepress->get_language_for_element( $job_details[ 'job_id' ], 'post_product' );
38
  $target_lang = $job_details[ 'target'];
42
  parent::__construct(
43
  $job_details[ 'job_id' ],
44
  'wc_product', __( 'Product', 'woocommerce-multilingual' ),
45
+ $this->original_post->post_title,
46
+ get_post_permalink( Deprecated_WC_Functions::get_product_id( $this->product ) ),
47
  $source_lang,
48
  $target_lang,
49
  $translation_complete,
59
 
60
  $translation_complete = false;
61
 
62
+ $product_trid = $this->sitepress->get_element_trid( $this->product_id, 'post_product' );
63
  $product_translations = $this->sitepress->get_element_translations( $product_trid, 'post_product', false, false, true );
64
  if ( isset( $this->job_details[ 'translation_complete' ] ) ) {
65
  $translation_complete = $this->job_details[ 'translation_complete' ];
81
 
82
  $is_duplicate_product = false;
83
 
84
+ $product_trid = $this->sitepress->get_element_trid( $this->product_id, 'post_product' );
85
  $product_translations = $this->sitepress->get_element_translations( $product_trid, 'post_product', false, false, true );
86
+ if ( isset( $product_translations[ $this->get_target_language() ] ) && get_post_meta( $product_translations[ $this->get_target_language() ]->element_id, '_icl_lang_duplicate_of', true ) === $this->product_id ) {
87
  $is_duplicate_product = true;
88
  }
89
 
107
  /*
108
  * Images
109
  */
110
+ $product_images = $this->woocommerce_wpml->media->product_images_ids( $this->product_id );
111
  // Exclude not-duplicated attachments and featured
112
+ $product_images = $this->woocommerce_wpml->media->exclude_not_duplicated_attachments( $product_images, $this->product_id );
113
 
114
  if ( count( $product_images ) ) {
115
 
135
  $this->add_field( $attributes_section );
136
  }
137
 
138
+ $custom_fields = $this->get_product_custom_fields_to_translate( $this->product_id );
139
+ if( $this->product_type === 'external' ){
140
  $custom_fields = array_diff( $custom_fields, array( '_product_url', '_button_text' ) );
141
  }
142
 
148
  $this->add_field( $custom_fields_section );
149
  }
150
 
151
+ if( $this->woocommerce_wpml->products->is_variable_product( $this->product_id ) ){
152
  $variations = $this->product->get_available_variations();
153
 
154
  if( !empty( $variations ) ){
165
 
166
  if( $this->product->is_downloadable() ){
167
  $is_variable = false;
168
+ if( $this->woocommerce_wpml->products->is_variable_product( $this->product_id ) ){
169
  $files_data = $this->get_files_for_variations();
170
  $is_variable = true;
171
  }else{
172
+ $files_data = array( $this->product_id => $this->woocommerce_wpml->downloadable->get_files_data( $this->product_id ) );
173
  }
174
 
175
  foreach( $files_data as $post_id => $file_data ){
204
  }
205
  }
206
 
207
+ if( $this->product_type === 'external' ){
208
  $external_product_section = new WPML_Editor_UI_Field_Section( __( 'External Product', 'woocommerce-multilingual' ) );
209
  $external_product_section->add_field( new WPML_Editor_UI_Single_Line_Field( '_product_url', __( 'Product url', 'woocommerce-multilingual' ), $this->data, true ) );
210
  $external_product_section->add_field( new WPML_Editor_UI_Single_Line_Field( '_button_text', __( 'Button text', 'woocommerce-multilingual' ), $this->data, true ) );
211
  $this->add_field( $external_product_section );
212
  }
213
 
214
+ do_action( 'wcml_gui_additional_box_html', $this, $this->product_id, $this->data );
215
 
216
  }
217
 
248
 
249
  function get_data() {
250
 
251
+ $trn_product_id = apply_filters( 'translate_object_id', $this->product_id, 'product', false, $this->get_target_language() );
252
  $translation = false;
253
  if ( null !== $trn_product_id ) {
254
  $translation = get_post( $trn_product_id );
255
  }
256
 
257
+ $element_data = array( 'title' => array( 'original' => $this->original_post->post_title ),
258
+ 'slug' => array( 'original' => urldecode( $this->original_post->post_name ) ),
259
+ 'product_content' => array( 'original' => $this->original_post->post_content ),
260
+ 'product_excerpt' => array( 'original' => $this->original_post->post_excerpt ),
261
+ '_purchase_note' => array( 'original' => get_post_meta( $this->product_id, '_purchase_note', true ) )
262
  );
263
 
264
  if ( $translation ) {
269
  $element_data[ '_purchase_note' ][ 'translation' ] = get_post_meta( $translation->ID, '_purchase_note', true );
270
  }
271
 
272
+ $product_images = $this->woocommerce_wpml->media->product_images_ids( $this->product_id );
273
  foreach( $product_images as $image_id ) {
274
  $attachment_data = $this->wpdb->get_row( $this->wpdb->prepare( "SELECT post_title,post_excerpt,post_content FROM {$this->wpdb->posts} WHERE ID = %d", $image_id ) );
275
  if( !$attachment_data ) continue;
298
  $element_data[ $attr_key.'_name' ] = array( 'original' => $attribute['name'] );
299
  $element_data[ $attr_key ] = array( 'original' => $attribute['value'] );
300
 
301
+ $trn_attribute = $this->woocommerce_wpml->attributes->get_custom_attribute_translation( $this->product_id, $attr_key, $attribute, $this->get_target_language() );
302
 
303
  $element_data[ $attr_key.'_name' ][ 'translation' ] = $trn_attribute['name'] ? $trn_attribute['name'] : '';
304
  $element_data[ $attr_key ][ 'translation' ] = $trn_attribute['value'] ? $trn_attribute['value'] : '';
305
  }
306
  }
307
 
308
+ $element_data = $this->add_custom_field_to_element_data( $element_data, $this->product_id, isset( $translation->ID ) ? $translation->ID : false, false );
309
 
310
+ if( $this->woocommerce_wpml->products->is_variable_product( $this->product_id ) ){
311
  $variations = $this->product->get_available_variations();
312
 
313
  if( !empty( $variations ) ){
322
  }
323
 
324
 
325
+ $files_data = array( $this->product_id => $this->woocommerce_wpml->downloadable->get_files_data( $this->product_id ) );
326
+ if( $this->woocommerce_wpml->products->is_variable_product( $this->product_id ) ){
327
  $files_data = $this->get_files_for_variations();
328
  }
329
 
350
  }
351
  }
352
 
353
+ $element_data = apply_filters( 'wcml_gui_additional_box_data', $element_data, $this->product_id, $translation, $this->get_target_language() );
354
 
355
  return $element_data;
356
  }
396
 
397
  $return = array();
398
 
399
+ if ( $this->original_post->post_type !== 'product' ) {
400
  return $return;
401
  }
402
 
403
  $languages = $this->sitepress->get_active_languages();
404
 
405
+ $product_trid = $this->sitepress->get_element_trid( $this->product_id, 'post_' . $this->original_post->post_type );
406
+ $tr_product_id = apply_filters( 'translate_object_id', $this->product_id, 'product', false, $this->get_target_language() );
407
 
408
  new WCML_Editor_Save_Filters( $product_trid, $this->get_target_language() );
409
  if ( get_magic_quotes_gpc() ) {
419
  //insert new post
420
  $args = array();
421
  $args[ 'post_title' ] = $translations[ md5( 'title' ) ];
422
+ $args[ 'post_type' ] = $this->original_post->post_type;
423
  $args[ 'post_content' ] = $translations[ md5( 'product_content' ) ];
424
  $args[ 'post_excerpt' ] = $translations[ md5( 'product_excerpt' ) ];
425
 
427
  return new WP_Error( 'empty_content', __( 'Content, title, and excerpt are empty.' ) );
428
  }
429
 
430
+ $args[ 'post_status' ] = $this->original_post->post_status;
431
+ $args[ 'menu_order '] = $this->original_post->menu_order;
432
+ $args[ 'ping_status' ] = $this->original_post->ping_status;
433
+ $args[ 'comment_status' ] = $this->original_post->comment_status;
434
+ $product_parent = apply_filters( 'translate_object_id', $this->original_post->post_parent, 'product', false, $this->get_target_language() );
435
  $args['post_parent'] = null === $product_parent ? 0 : $product_parent;
436
 
437
  //TODO: remove after change required WPML version > 3.3
440
  $_POST[ 'icl_post_language' ] = $this->get_target_language();
441
 
442
  if ( $this->woocommerce_wpml->settings[ 'products_sync_date' ] ) {
443
+ $args[ 'post_date' ] = $this->original_post->post_date;
444
  }
445
 
446
  $tr_product_id = wp_insert_post( $args );
459
 
460
  $this->wpdb->update( $this->wpdb->prefix . 'icl_translations', array( 'element_id' => $tr_product_id ), array( 'translation_id' => $translation_id ) );
461
  } else {
462
+ $this->sitepress->set_element_language_details( $tr_product_id, 'post_' . $this->original_post->post_type, $product_trid, $this->get_target_language() );
463
  }
464
 
465
  } else {
469
  $args[ 'post_title' ] = $translations[ md5( 'title' ) ];
470
  $args[ 'post_content' ] = $translations[ md5( 'product_content' ) ];
471
  $args[ 'post_excerpt' ] = $translations[ md5( 'product_excerpt' ) ];
472
+ $args[ 'post_status' ] = $this->original_post->post_status;
473
+ $args[ 'ping_status' ] = $this->original_post->ping_status;
474
+ $args[ 'comment_status' ] = $this->original_post->comment_status;
475
+ $product_parent = apply_filters( 'translate_object_id', $this->original_post->post_parent, 'product', false, $this->get_target_language() );
476
  $args['post_parent'] = null === $product_parent ? 0 : $product_parent;
477
  $_POST[ 'to_lang' ] = $this->get_target_language();
478
 
488
  $new_post_name = sanitize_title( $translations[ md5( 'slug' ) ] ? $translations[ md5( 'slug' ) ] : $translations[ md5( 'title' ) ]);
489
  $_POST[ 'new_title' ] = $translations[ md5( 'title' ) ];
490
  $_POST[ 'new_slug' ] = $new_post_name;
491
+ $new_slug = wp_unique_post_slug( $new_post_name, $tr_product_id, $this->original_post->post_status, $this->original_post->post_type, $args[ 'post_parent' ] );
492
  $this->wpdb->update( $this->wpdb->posts, array( 'post_name' => $new_slug ), array( 'ID' => $tr_product_id ) );
493
  }
494
 
495
+ $this->sitepress->set_element_language_details( $tr_product_id, 'post_' . $this->original_post->post_type, $product_trid, $this->get_target_language() );
496
 
497
  }
498
 
499
  $product_translations = $this->sitepress->get_element_translations( $product_trid , 'post_product', false, false, true );
500
 
501
+ do_action( 'wcml_before_sync_product_data', $this->product_id, $tr_product_id, $this->get_target_language() );
502
 
503
+ $this->woocommerce_wpml->sync_product_data->duplicate_product_post_meta( $this->product_id, $tr_product_id, $translations );
504
 
505
  //sync taxonomies
506
+ $this->woocommerce_wpml->sync_product_data->sync_product_taxonomies( $this->product_id, $tr_product_id, $this->get_target_language() );
507
 
508
+ do_action( 'wcml_update_extra_fields', $this->product_id, $tr_product_id, $translations, $this->get_target_language() );
509
 
510
+ $this->woocommerce_wpml->attributes->sync_product_attr( $this->product_id, $tr_product_id, $this->get_target_language(), $translations );
511
 
512
+ $this->woocommerce_wpml->attributes->sync_default_product_attr( $this->product_id, $tr_product_id, $this->get_target_language() );
513
 
514
  //sync media
515
  if ( $this->woocommerce_wpml->media->settings[ 'duplicate_featured' ] ) {
516
  //sync feature image
517
+ $this->woocommerce_wpml->media->sync_thumbnail_id( $this->product_id, $tr_product_id, $this->get_target_language() );
518
  }
519
 
520
  if ( $this->woocommerce_wpml->media->settings[ 'duplicate_media' ] ) {
521
  //sync product gallery
522
+ $this->woocommerce_wpml->media->sync_product_gallery( $this->product_id );
523
  }
524
 
525
  // synchronize post variations
526
+ $this->woocommerce_wpml->sync_variations_data->sync_product_variations( $this->product_id, $tr_product_id, $this->get_target_language(), $translations );
527
 
528
+ $this->woocommerce_wpml->sync_product_data->sync_linked_products( $this->product_id, $tr_product_id, $this->get_target_language() );
529
  //save images texts
530
+ $product_images = $this->woocommerce_wpml->media->product_images_ids( $this->product_id );
531
 
532
  if ( $product_images ) {
533
  foreach ( $product_images as $image_id ) {
563
  }
564
  ob_start();
565
 
566
+ $this->woocommerce_wpml->products->get_translation_statuses( $this->product_id, $product_translations, $languages, isset( $translations['slang'] )
567
  && $translations['slang']
568
  !== 'all' ? $translations['slang'] : false, $product_trid, $this->get_target_language() );
569
  $return[ 'status_link' ] = ob_get_clean();
570
 
571
  // no longer a duplicate
572
+ delete_post_meta( $tr_product_id, '_icl_lang_duplicate_of', $this->product_id );
573
 
574
  return $return;
575
 
577
 
578
  public function get_custom_product_atributes( )
579
  {
580
+ $attributes = get_post_meta( $this->product_id, '_product_attributes', true);
581
  if (!is_array($attributes)) {
582
  $attributes = array();
583
  }
602
  return false;
603
  }
604
 
605
+ $exception = apply_filters('wcml_product_content_exception', true, $this->product_id, $field);
606
  if ( !$exception ) {
607
  return false;
608
  }
609
 
610
+ $custom_key_label = apply_filters('wcml_product_content_label', $field, $this->product_id);
611
  if ( $custom_key_label !== $field ) {
612
  $label = $custom_key_label;
613
  return $label;
629
 
630
  global $wpdb;
631
 
632
+ $variations = $wpdb->get_results($wpdb->prepare("SELECT * FROM $wpdb->posts WHERE post_parent = %d AND post_type = 'product_variation'", $this->product_id));
633
  $variations_files = array();
634
 
635
  foreach ($variations as $variation) {
inc/translation-editor/class-wcml-synchronize-product-data.php CHANGED
@@ -1,639 +1,649 @@
1
- <?php
2
-
3
- class WCML_Synchronize_Product_Data{
4
-
5
- private $woocommerce_wpml;
6
- /**
7
- * @var SitePress
8
- */
9
- private $sitepress;
10
- private $wpdb;
11
-
12
- public function __construct( &$woocommerce_wpml, &$sitepress, &$wpdb ) {
13
- $this->woocommerce_wpml = $woocommerce_wpml;
14
- $this->sitepress = $sitepress;
15
- $this->wpdb = $wpdb;
16
-
17
- if( is_admin() ){
18
- // filters to sync variable products
19
- add_action( 'save_post', array( $this, 'sync_post_action' ), 110, 2 ); // After WPML
20
-
21
- add_action( 'icl_pro_translation_completed', array( $this, 'icl_pro_translation_completed' ) );
22
-
23
- add_filter( 'icl_make_duplicate', array( $this, 'icl_make_duplicate'), 110, 4 );
24
- add_action( 'woocommerce_duplicate_product', array( $this, 'woocommerce_duplicate_product' ), 10, 2 );
25
-
26
- //quick & bulk edit
27
- add_action( 'woocommerce_product_quick_edit_save', array( $this, 'woocommerce_product_quick_edit_save' ) );
28
- add_action( 'woocommerce_product_bulk_edit_save', array( $this, 'woocommerce_product_quick_edit_save' ) );
29
-
30
- add_action( 'init', array( $this, 'init' ) );
31
-
32
- add_action( 'deleted_term_relationships', array( $this, 'delete_term_relationships_update_term_count' ), 10, 2 );
33
- }
34
-
35
- add_action( 'woocommerce_reduce_order_stock', array( $this, 'sync_product_stocks_reduce' ) );
36
- add_action( 'woocommerce_restore_order_stock', array( $this, 'sync_product_stocks_restore' ) );
37
- add_action( 'woocommerce_product_set_stock_status', array($this, 'sync_stock_status_for_translations' ), 10, 2);
38
- add_action( 'woocommerce_variation_set_stock_status', array($this, 'sync_stock_status_for_translations' ), 10, 2);
39
-
40
- add_filter( 'future_product', array( $this, 'set_schedule_for_translations'), 10, 2 );
41
- }
42
-
43
- public function init(){
44
- $this->check_ajax_actions();
45
- }
46
-
47
- /**
48
- * This function takes care of synchronizing original product
49
- */
50
- public function sync_post_action( $post_id, $post ){
51
- global $pagenow, $wp;
52
-
53
- $original_language = $this->woocommerce_wpml->products->get_original_product_language( $post_id );
54
- $current_language = $this->sitepress->get_current_language();
55
- $duplicated_post_id = apply_filters( 'translate_object_id', $post_id, 'product', false, $original_language );
56
-
57
- $wpml_media_options = maybe_unserialize( get_option( '_wpml_media' ) );
58
-
59
- if( $wpml_media_options[ 'new_content_settings' ][ 'duplicate_media' ] ){
60
- //sync product gallery
61
- $this->woocommerce_wpml->media->sync_product_gallery( $duplicated_post_id );
62
- }
63
- // check its a product
64
- $post_type = get_post_type( $post_id );
65
- //set trid for variations
66
- if ( $post_type == 'product_variation' ) {
67
- $var_lang = $this->sitepress->get_language_for_element( wp_get_post_parent_id( $post_id ), 'post_product' );
68
- if( $this->woocommerce_wpml->products->is_original_product( wp_get_post_parent_id( $post_id ) ) ){
69
- $this->sitepress->set_element_language_details( $post_id, 'post_product_variation', false, $var_lang );
70
- }
71
- }
72
-
73
- if ( $post_type != 'product' ) {
74
- return;
75
- }
76
-
77
- // exceptions
78
- $ajax_call = ( !empty( $_POST[ 'icl_ajx_action' ] ) && $_POST[ 'icl_ajx_action' ] == 'make_duplicates' );
79
- $api_call = !empty( $wp->query_vars['wc-api-version'] );
80
- if ( ( empty( $duplicated_post_id ) || isset( $_POST[ 'autosave' ] ) ) ||
81
- ( $pagenow != 'post.php' && $pagenow != 'post-new.php' && $pagenow != 'admin.php' && !$ajax_call && !$api_call ) ||
82
- ( isset( $_GET[ 'action' ] ) && $_GET[ 'action' ] == 'trash' )
83
- ) {
84
- return;
85
- }
86
- // If we reach this point, we go ahead with sync.
87
- // Remove filter to avoid double sync
88
- remove_action( 'save_post', array( $this, 'sync_post_action' ), 110, 2 );
89
- do_action( 'wcml_before_sync_product', $duplicated_post_id, $post_id );
90
-
91
-
92
- //trnsl_interface option
93
- if ( !$this->woocommerce_wpml->settings['trnsl_interface'] && $original_language != $current_language ) {
94
- if( !isset( $_POST[ 'wp-preview' ] ) || empty( $_POST[ 'wp-preview' ] ) ){
95
- //make sure we sync post in current language
96
- $post_id = apply_filters( 'translate_object_id', $post_id, 'product', false, $current_language );
97
- do_action( 'wcml_before_sync_product_data', $duplicated_post_id, $post_id, $current_language );
98
- $this->sync_date_and_parent( $duplicated_post_id, $post_id, $current_language );
99
- $this->sync_product_data( $duplicated_post_id, $post_id, $current_language );
100
- }
101
- return;
102
- }
103
-
104
- // get language code
105
- $language_details = $this->sitepress->get_element_language_details( $post_id, 'post_product' );
106
- if ( $pagenow == 'admin.php' && empty( $language_details ) ) {
107
- //translation editor support: sidestep icl_translations_cache
108
- $language_details = $this->wpdb->get_row(
109
- $this->wpdb->prepare(
110
- "SELECT element_id, trid, language_code, source_language_code FROM {$this->wpdb->prefix}icl_translations
111
- WHERE element_id = %d AND element_type = 'post_product'",
112
- $post_id )
113
- );
114
- }
115
- if ( empty( $language_details ) ) {
116
- return;
117
- }
118
-
119
- //save files option
120
- $this->woocommerce_wpml->downloadable->save_files_option( $duplicated_post_id );
121
- // pick posts to sync
122
- $traslated_products = array();
123
- $translations = $this->sitepress->get_element_translations( $language_details->trid, 'post_product', false, true );
124
-
125
- foreach ( $translations as $translation ) {
126
- if ( $translation->original ) {
127
- $original_product_id = $translation->element_id;
128
- } else {
129
- $traslated_products[ $translation->element_id ] = $translation;
130
- }
131
- }
132
-
133
- foreach( $traslated_products as $translated_product_id => $translation ) {
134
- $lang = $translation->language_code;
135
- do_action( 'wcml_before_sync_product_data', $original_product_id, $translated_product_id, $lang );
136
- // Filter upsell products, crosell products and default attributes for translations
137
- $this->duplicate_product_post_meta( $original_product_id, $translated_product_id );
138
- if( $wpml_media_options[ 'new_content_settings' ][ 'duplicate_featured' ] ){
139
- //sync feature image
140
- $this->woocommerce_wpml->media->sync_thumbnail_id( $original_product_id, $translated_product_id, $lang );
141
- }
142
- $this->sync_date_and_parent( $original_product_id, $translated_product_id, $lang );
143
- $this->sync_product_taxonomies( $original_product_id, $translated_product_id, $lang );
144
- $this->woocommerce_wpml->attributes->sync_default_product_attr( $original_product_id, $translated_product_id, $lang );
145
- $this->woocommerce_wpml->attributes->sync_product_attr( $original_product_id, $translated_product_id );
146
- $this->woocommerce_wpml->products->update_order_for_product_translations( $original_product_id );
147
- // synchronize post variations
148
- $this->woocommerce_wpml->sync_variations_data->sync_product_variations( $original_product_id, $translated_product_id, $lang );
149
- $this->sync_linked_products( $original_product_id, $translated_product_id, $lang );
150
-
151
- // Clear any unwanted data
152
- wc_delete_product_transients( $translated_product_id );
153
- }
154
- if( $this->woocommerce_wpml->settings['enable_multi_currency'] == WCML_MULTI_CURRENCIES_INDEPENDENT ) {
155
- //save custom prices
156
- $this->woocommerce_wpml->multi_currency->custom_prices->save_custom_prices( $duplicated_post_id );
157
- $this->woocommerce_wpml->multi_currency->custom_prices->sync_product_variations_custom_prices($original_product_id);
158
- }
159
- }
160
-
161
- public function sync_product_data( $original_product_id, $tr_product_id, $lang ){
162
-
163
- $this->duplicate_product_post_meta( $original_product_id, $tr_product_id );
164
-
165
- $this->woocommerce_wpml->attributes->sync_product_attr( $original_product_id, $tr_product_id );
166
-
167
- $this->woocommerce_wpml->attributes->sync_default_product_attr( $original_product_id, $tr_product_id, $lang );
168
-
169
- $wpml_media_options = maybe_unserialize( get_option( '_wpml_media' ) );
170
- //sync media
171
- if( $wpml_media_options[ 'new_content_settings' ][ 'duplicate_featured' ] ){
172
- //sync feature image
173
- $this->woocommerce_wpml->media->sync_thumbnail_id( $original_product_id, $tr_product_id, $lang );
174
- }
175
-
176
- if( $wpml_media_options[ 'new_content_settings' ][ 'duplicate_media' ]){
177
- //sync product gallery
178
- $this->woocommerce_wpml->media->sync_product_gallery( $original_product_id );
179
- }
180
-
181
- //sync taxonomies
182
- $this->sync_product_taxonomies( $original_product_id, $tr_product_id, $lang );
183
-
184
- //duplicate variations
185
-
186
- $this->woocommerce_wpml->sync_variations_data->sync_product_variations( $original_product_id, $tr_product_id, $lang );
187
-
188
- $this->sync_linked_products( $original_product_id, $tr_product_id, $lang );
189
-
190
- // Clear any unwanted data
191
- wc_delete_product_transients( $tr_product_id );
192
- }
193
-
194
- public function sync_product_taxonomies( $original_product_id, $tr_product_id, $lang ){
195
- $taxonomies = get_object_taxonomies( 'product' );
196
-
197
- foreach( $taxonomies as $taxonomy ) {
198
-
199
- $terms = wp_get_object_terms( $original_product_id, $taxonomy );
200
- $tt_ids = array();
201
- $tt_names = array();
202
- if ($terms) {
203
- foreach ($terms as $term) {
204
- if( $term->taxonomy == 'product_type' ){
205
- $tt_names[] = $term->name;
206
- continue;
207
- }
208
- $tt_ids[] = $term->term_id;
209
- }
210
-
211
- if( $taxonomy == 'product_type' ) {
212
- wp_set_post_terms( $tr_product_id, $tt_names, $taxonomy );
213
- }else{
214
- $this->wcml_update_term_count_by_ids( $tt_ids, $lang, $taxonomy, $tr_product_id );
215
- }
216
- }
217
- }
218
- }
219
-
220
- public function delete_term_relationships_update_term_count( $object_id, $tt_ids ){
221
-
222
- if( get_post_type( $object_id ) == 'product' ){
223
-
224
- $language_details = $this->sitepress->get_element_language_details( $object_id, 'post_product' );
225
- $translations = $this->sitepress->get_element_translations( $language_details->trid, 'post_product', false, true );
226
-
227
- foreach( $translations as $translation ) {
228
- if ( !$translation->original ) {
229
- $this->wcml_update_term_count_by_ids( $tt_ids, $translation->language_code );
230
- }
231
- }
232
- }
233
-
234
- }
235
- public function wcml_update_term_count_by_ids( $tt_ids, $language, $taxonomy = '', $tr_product_id = false ){
236
- $terms_array = array();
237
- $terms_ids_array = array();
238
-
239
- foreach( $tt_ids as $tt_id ){
240
-
241
- $tr_id = apply_filters( 'translate_object_id', $tt_id, $taxonomy, false, $language );
242
-
243
- if( !is_null( $tr_id ) ){
244
- // not using get_term - unfiltered get_term
245
- $translated_term = $this->wpdb->get_row( $this->wpdb->prepare( "
246
- SELECT * FROM {$this->wpdb->terms} t JOIN {$this->wpdb->term_taxonomy} x ON x.term_id = t.term_id WHERE t.term_id = %d", $tr_id ) );
247
- $terms_ids_array[] = $translated_term->term_id;
248
- $terms_array[] = $translated_term->term_taxonomy_id;
249
- $taxonomy = $translated_term->taxonomy;
250
- }
251
-
252
- }
253
-
254
- if( is_taxonomy_hierarchical( $taxonomy ) ){
255
- $terms_array = array_unique( array_map( 'intval', $terms_array ) );
256
- }
257
-
258
-
259
- if( in_array( $taxonomy, array( 'product_cat', 'product_tag' ) ) ) {
260
- $this->sitepress->switch_lang( $language );
261
- wp_update_term_count( $terms_array, $taxonomy );
262
- $this->sitepress->switch_lang( );
263
- }elseif( $tr_product_id ){
264
- wp_set_post_terms( $tr_product_id, $terms_ids_array, $taxonomy );
265
- }
266
-
267
- }
268
-
269
- public function sync_linked_products( $product_id, $translated_product_id, $lang ){
270
- //sync up-sells
271
- $original_up_sells = maybe_unserialize( get_post_meta( $product_id, '_upsell_ids', true ) );
272
- $trnsl_up_sells = array();
273
- if( $original_up_sells ){
274
- foreach( $original_up_sells as $original_up_sell_product ) {
275
- $trnsl_up_sells[] = apply_filters( 'translate_object_id', $original_up_sell_product, get_post_type( $original_up_sell_product ), false, $lang );
276
- }
277
- }
278
- update_post_meta( $translated_product_id, '_upsell_ids', $trnsl_up_sells );
279
- //sync cross-sells
280
- $original_cross_sells = maybe_unserialize( get_post_meta( $product_id, '_crosssell_ids', true ) );
281
- $trnsl_cross_sells = array();
282
- if( $original_cross_sells )
283
- foreach( $original_cross_sells as $original_cross_sell_product ){
284
- $trnsl_cross_sells[] = apply_filters( 'translate_object_id', $original_cross_sell_product, get_post_type( $original_cross_sell_product ), false, $lang );
285
- }
286
- update_post_meta( $translated_product_id, '_crosssell_ids', $trnsl_cross_sells );
287
- // refresh parent-children transients (e.g. this child goes to private or draft)
288
- $translated_product_parent_id = wp_get_post_parent_id( $translated_product_id );
289
- if ( $translated_product_parent_id ) {
290
- delete_transient( 'wc_product_children_' . $translated_product_parent_id );
291
- delete_transient( '_transient_wc_product_children_ids_' . $translated_product_parent_id );
292
- }
293
- }
294
-
295
-
296
-
297
- public function sync_product_stocks_reduce( $order ){
298
- return $this->sync_product_stocks( $order, 'reduce' );
299
- }
300
-
301
- public function sync_product_stocks_restore( $order ){
302
- return $this->sync_product_stocks( $order, 'restore' );
303
- }
304
-
305
- /**
306
- * @param $order WC_Order
307
- * @param $action
308
- */
309
- public function sync_product_stocks( $order, $action ){
310
- $order_id = method_exists( 'WC_Order', 'get_id' ) ? $order->get_id() : $order->id;
311
-
312
- foreach( $order->get_items() as $item ) {
313
-
314
- if( $item instanceof WC_Order_Item_Product ){
315
- $variation_id = $item->get_variation_id();
316
- $product_id = $item->get_product_id();
317
- $qty = $item->get_quantity();
318
- }else{
319
- $variation_id = isset( $item[ 'variation_id' ] ) ? $item[ 'variation_id' ] : 0;
320
- $product_id = $item[ 'product_id' ];
321
- $qty = $item[ 'qty' ];
322
- }
323
-
324
- if( $variation_id > 0 ){
325
- $trid = $this->sitepress->get_element_trid( $variation_id, 'post_product_variation' );
326
- $translations = $this->sitepress->get_element_translations( $trid, 'post_product_variation' );
327
- $ld = $this->sitepress->get_element_language_details( $variation_id, 'post_product_variation' );
328
- } else {
329
- $trid = $this->sitepress->get_element_trid( $product_id, 'post_product' );
330
- $translations = $this->sitepress->get_element_translations( $trid, 'post_product' );
331
- $ld = $this->sitepress->get_element_language_details( $product_id, 'post_product' );
332
- }
333
-
334
- // Process for non-current languages
335
- foreach( $translations as $translation ){
336
- if ( $ld->language_code != $translation->language_code ) {
337
- //check if product exist
338
- if( get_post_type( $translation->element_id ) == 'product_variation' && !get_post( wp_get_post_parent_id( $translation->element_id ) ) ){
339
- continue;
340
- }
341
- $_product = wc_get_product( $translation->element_id );
342
-
343
- if( $_product && $_product->exists() && $_product->managing_stock() ) {
344
- $total_sales = get_post_meta($_product->id, 'total_sales', true);
345
-
346
- if( $action == 'reduce'){
347
- $stock = $_product->reduce_stock( $qty );
348
- $total_sales += $qty;
349
- }else{
350
- $stock = $_product->increase_stock( $qty );
351
- $total_sales -= $qty;
352
- }
353
- update_post_meta( $translation->element_id, 'total_sales', $total_sales );
354
- }
355
- }
356
- }
357
- }
358
- }
359
-
360
- public function sync_stock_status_for_translations( $id, $status ){
361
-
362
- $type = get_post_type( $id );
363
- $trid = $this->sitepress->get_element_trid( $id, 'post_'.$type );
364
- $translations = $this->sitepress->get_element_translations( $trid, 'post_'.$type, true);
365
-
366
- foreach ( $translations as $translation ) {
367
- if ( !$translation->original ) {
368
- update_post_meta( $translation->element_id, '_stock_status', $status );
369
- }
370
- }
371
- }
372
-
373
-
374
-
375
- //sync product parent & post_status
376
- public function sync_date_and_parent( $duplicated_post_id, $post_id, $lang ){
377
- $tr_parent_id = apply_filters( 'translate_object_id', wp_get_post_parent_id( $duplicated_post_id ), 'product', false, $lang );
378
- $orig_product = get_post( $duplicated_post_id );
379
- $args = array();
380
- $args[ 'post_parent' ] = is_null( $tr_parent_id )? 0 : $tr_parent_id;
381
- //sync product date
382
-
383
- if( !empty( $this->woocommerce_wpml->settings[ 'products_sync_date' ] ) ){
384
- $args[ 'post_date' ] = $orig_product->post_date;
385
- }
386
- $this->wpdb->update(
387
- $this->wpdb->posts,
388
- $args,
389
- array( 'id' => $post_id )
390
- );
391
- }
392
-
393
- public function set_schedule_for_translations( $deprecated, $post ){
394
-
395
- if( $this->woocommerce_wpml->products->is_original_product( $post->ID ) ) {
396
- $trid = $this->sitepress->get_element_trid( $post->ID, 'post_product');
397
- $translations = $this->sitepress->get_element_translations( $trid, 'post_product', true);
398
- foreach( $translations as $translation ) {
399
- if( !$translation->original ){
400
- wp_clear_scheduled_hook( 'publish_future_post', array( $translation->element_id ) );
401
- wp_schedule_single_event( strtotime( get_gmt_from_date( $post->post_date) . ' GMT' ), 'publish_future_post', array( $translation->element_id ) );
402
- }
403
- }
404
- }
405
- }
406
-
407
-
408
-
409
- public function icl_pro_translation_completed( $tr_product_id ){
410
- $trid = $this->sitepress->get_element_trid( $tr_product_id, 'post_product' );
411
- $translations = $this->sitepress->get_element_translations( $trid, 'post_product' );
412
-
413
- foreach( $translations as $translation ){
414
- if( $translation->original ){
415
- $original_product_id = $translation->element_id;
416
- }
417
- }
418
-
419
- if( !isset( $original_product_id ) ){
420
- return;
421
- }
422
-
423
- $lang = $this->sitepress->get_language_for_element( $tr_product_id, 'post_product' );
424
- $this->sync_product_data( $original_product_id, $tr_product_id, $lang );
425
- }
426
-
427
- public function icl_make_duplicate( $master_post_id, $lang, $postarr, $id ){
428
- if( get_post_type( $master_post_id ) == 'product' ){
429
-
430
- $original_language = $this->woocommerce_wpml->products->get_original_product_language( $master_post_id );
431
- $master_post_id = apply_filters( 'translate_object_id', $master_post_id, 'product', false, $original_language );
432
-
433
- $this->sync_product_data( $master_post_id, $id, $lang );
434
- }
435
- }
436
-
437
- public function woocommerce_product_quick_edit_save( $product ){
438
- $is_original = $this->woocommerce_wpml->products->is_original_product( $product->id );
439
- $trid = $this->sitepress->get_element_trid( $product->id, 'post_product' );
440
-
441
- if( $trid ){
442
- $translations = $this->sitepress->get_element_translations( $trid, 'post_product' );
443
- if( $translations ){
444
- foreach( $translations as $translation ){
445
- if( $is_original ){
446
- if( !$translation->original ){
447
- $this->sync_product_data( $product->id, $translation->element_id, $translation->language_code );
448
- $this->sync_date_and_parent( $product->id, $translation->element_id, $translation->language_code );
449
- }
450
- }elseif( $translation->original ){
451
- $this->sync_product_data( $translation->element_id, $product->id, $this->sitepress->get_language_for_element( $product->id, 'post_product' ) );
452
- $this->sync_date_and_parent( $translation->element_id, $product->id, $this->sitepress->get_language_for_element( $product->id, 'post_product' ) );
453
- }
454
- }
455
- }
456
- }
457
- }
458
-
459
-
460
-
461
- //duplicate product post meta
462
- public function duplicate_product_post_meta( $original_product_id, $trnsl_product_id, $data = false ){
463
- global $iclTranslationManagement;
464
- $settings = $iclTranslationManagement->settings[ 'custom_fields_translation' ];
465
- $all_meta = get_post_custom( $original_product_id );
466
- $post_fields = null;
467
-
468
- unset( $all_meta[ '_thumbnail_id' ] );
469
-
470
- foreach ( $all_meta as $key => $meta ) {
471
- if ( !isset( $settings[ $key ] ) || $settings[ $key ] == WPML_IGNORE_CUSTOM_FIELD ) {
472
- continue;
473
- }
474
- foreach ( $meta as $meta_value ) {
475
- if( $key == '_downloadable_files' ){
476
- $this->woocommerce_wpml->downloadable->sync_files_to_translations( $original_product_id, $trnsl_product_id, $data );
477
- }elseif ( $data ) {
478
- if ( isset( $settings[ $key ] ) && $settings[ $key ] == WPML_TRANSLATE_CUSTOM_FIELD ) {
479
-
480
- $post_fields = $this->sync_custom_field_value( $key, $data, $trnsl_product_id, $post_fields );
481
- }
482
- }
483
- }
484
- }
485
-
486
- do_action( 'wcml_after_duplicate_product_post_meta', $original_product_id, $trnsl_product_id, $data );
487
- }
488
-
489
- public function sync_custom_field_value( $custom_field, $translation_data, $trnsl_product_id, $post_fields, $original_product_id = false, $is_variation = false ){
490
-
491
- if( is_null( $post_fields ) ){
492
- $post_fields = array();
493
- if( isset( $_POST['data'] ) ){
494
- $post_args = wp_parse_args( $_POST['data'] );
495
- $post_fields = $post_args[ 'fields' ];
496
- }
497
- }
498
-
499
-
500
- $custom_filed_key = $is_variation && $original_product_id ? $custom_field.$original_product_id : $custom_field;
501
-
502
- if( isset( $translation_data[ md5( $custom_filed_key ) ] ) ){
503
- $meta_value = $translation_data[ md5( $custom_filed_key ) ];
504
- $meta_value = apply_filters( 'wcml_meta_value_before_add', $meta_value, $custom_filed_key );
505
- update_post_meta( $trnsl_product_id, $custom_field, $meta_value );
506
- unset( $post_fields[ $custom_filed_key ] );
507
- }else{
508
- foreach( $post_fields as $post_field_key => $post_field ){
509
- $meta_value = $translation_data[ md5( $post_field_key ) ];
510
- $field_key = explode( ':', $post_field_key );
511
- if( $field_key[0] == $custom_filed_key ){
512
- if( substr( $field_key[1], 0, 3 ) == 'new' ){
513
- add_post_meta( $trnsl_product_id, $custom_field, $meta_value );
514
- }else{
515
- update_meta( $field_key[1], $custom_field, $meta_value );
516
- }
517
- unset( $post_fields[ $post_field_key ] );
518
- }
519
- }
520
- }
521
-
522
- return $post_fields;
523
- }
524
-
525
- public function woocommerce_duplicate_product( $new_id, $post ){
526
- $duplicated_products = array();
527
-
528
- //duplicate original first
529
- $trid = $this->sitepress->get_element_trid( $post->ID, 'post_' . $post->post_type );
530
- $orig_id = $this->sitepress->get_original_element_id_by_trid( $trid );
531
- $orig_lang = $this->woocommerce_wpml->products->get_original_product_language( $post->ID );
532
-
533
- $wc_admin = new WC_Admin_Duplicate_Product();
534
-
535
- if( $orig_id == $post->ID ){
536
- $this->sitepress->set_element_language_details( $new_id, 'post_' . $post->post_type, false, $orig_lang );
537
- $new_trid = $this->sitepress->get_element_trid( $new_id, 'post_' . $post->post_type );
538
- $new_orig_id = $new_id;
539
- }else{
540
- $post_to_duplicate = $this->wpdb->get_row( $this->wpdb->prepare( "SELECT * FROM {$this->wpdb->posts} WHERE ID=%d", $orig_id ) );
541
- if ( ! empty( $post_to_duplicate ) ) {
542
- $new_orig_id = $wc_admin->duplicate_product( $post_to_duplicate );
543
- do_action( 'wcml_after_duplicate_product' , $new_id, $post_to_duplicate );
544
- $this->sitepress->set_element_language_details( $new_orig_id, 'post_' . $post->post_type, false, $orig_lang );
545
- $new_trid = $this->sitepress->get_element_trid( $new_orig_id, 'post_' . $post->post_type );
546
- if( get_post_meta( $orig_id, '_icl_lang_duplicate_of' ) ){
547
- update_post_meta( $new_id, '_icl_lang_duplicate_of', $new_orig_id );
548
- }
549
- $this->sitepress->set_element_language_details( $new_id, 'post_' . $post->post_type, $new_trid, $this->sitepress->get_current_language() );
550
- }
551
- }
552
-
553
- // Set language info for variations
554
- if ( $children_products = get_children( 'post_parent=' . $new_orig_id . '&post_type=product_variation' ) ) {
555
- foreach ( $children_products as $child ) {
556
- $this->sitepress->set_element_language_details( $child->ID, 'post_product_variation', false, $orig_lang );
557
- }
558
- }
559
-
560
- $translations = $this->sitepress->get_element_translations( $trid, 'post_' . $post->post_type );
561
- $duplicated_products[ 'translations' ] = array();
562
- if( $translations ){
563
- foreach( $translations as $translation ){
564
- if( !$translation->original && $translation->element_id != $post->ID ){
565
- $post_to_duplicate = $this->wpdb->get_row( $this->wpdb->prepare( "SELECT * FROM {$this->wpdb->posts} WHERE ID=%d", $translation->element_id ) );
566
-
567
- if( ! empty( $post_to_duplicate ) ) {
568
- $new_id = $wc_admin->duplicate_product( $post_to_duplicate );
569
- $new_id_obj = get_post( $new_id );
570
- $new_slug = wp_unique_post_slug( sanitize_title( $new_id_obj->post_title ), $new_id, $post_to_duplicate->post_status, $post_to_duplicate->post_type, $new_id_obj->post_parent );
571
-
572
- $this->wpdb->update(
573
- $this->wpdb->posts,
574
- array(
575
- 'post_name' => $new_slug,
576
- 'post_status' => 'draft'
577
- ),
578
- array( 'ID' => $new_id )
579
- );
580
-
581
- do_action( 'wcml_after_duplicate_product' , $new_id, $post_to_duplicate );
582
- $this->sitepress->set_element_language_details( $new_id, 'post_' . $post->post_type, $new_trid, $translation->language_code );
583
- if( get_post_meta( $translation->element_id, '_icl_lang_duplicate_of' ) ){
584
- update_post_meta( $new_id, '_icl_lang_duplicate_of', $new_orig_id );
585
- }
586
- $duplicated_products[ 'translations' ][] = $new_id;
587
- }
588
- }
589
- }
590
- }
591
-
592
- $duplicated_products[ 'original' ] = $new_orig_id;
593
-
594
- return $duplicated_products;
595
- }
596
-
597
- public function check_ajax_actions(){
598
- if( isset( $_POST[ 'icl_ajx_action' ] ) && $_POST[ 'icl_ajx_action' ] == 'connect_translations' ){
599
- $this->icl_connect_translations_action();
600
- }
601
- }
602
-
603
- public function icl_connect_translations_action(){
604
- $new_trid = $_POST['new_trid'];
605
- $post_type = $_POST['post_type'];
606
- $post_id = $_POST['post_id'];
607
- $set_as_source = $_POST['set_as_source'];
608
- if( $post_type == 'product' ){
609
-
610
- $translations = $this->sitepress->get_element_translations( $new_trid, 'post_' . $post_type );
611
- if( $translations ) {
612
- foreach ( $translations as $translation ) {
613
- //current as original need sync translation
614
- if ( $translation->original ) {
615
- if( $set_as_source ) {
616
- $orig_id = $post_id;
617
- $trnsl_id = $translation->element_id;
618
- $lang = $translation->language_code;
619
- }else{
620
- $orig_id = $translation->element_id;
621
- $trnsl_id = $post_id;
622
- $lang = $this->sitepress->get_current_language();
623
- }
624
- $this->sync_product_data( $orig_id, $trnsl_id, $lang );
625
- $this->sync_date_and_parent( $orig_id, $trnsl_id, $lang );
626
- $this->sitepress->copy_custom_fields( $orig_id, $trnsl_id );
627
- }else {
628
- if( $set_as_source ) {
629
- $this->sync_product_data( $post_id, $translation->element_id, $translation->language_code );
630
- $this->sync_date_and_parent( $post_id, $translation->element_id, $translation->language_code );
631
- $this->sitepress->copy_custom_fields( $post_id, $translation->element_id );
632
- }
633
- }
634
- }
635
- }
636
- }
637
- }
638
-
 
 
 
 
 
 
 
 
 
 
639
  }
1
+ <?php
2
+
3
+ class WCML_Synchronize_Product_Data{
4
+
5
+ private $woocommerce_wpml;
6
+ /**
7
+ * @var SitePress
8
+ */
9
+ private $sitepress;
10
+ private $wpdb;
11
+
12
+ public function __construct( &$woocommerce_wpml, &$sitepress, &$wpdb ) {
13
+ $this->woocommerce_wpml = $woocommerce_wpml;
14
+ $this->sitepress = $sitepress;
15
+ $this->wpdb = $wpdb;
16
+
17
+ if( is_admin() ){
18
+ // filters to sync variable products
19
+ add_action( 'save_post', array( $this, 'synchronize_products' ), 110, 2 ); // After WPML
20
+
21
+ add_action( 'icl_pro_translation_completed', array( $this, 'icl_pro_translation_completed' ) );
22
+
23
+ add_filter( 'icl_make_duplicate', array( $this, 'icl_make_duplicate'), 110, 4 );
24
+ add_action( 'woocommerce_duplicate_product', array( $this, 'woocommerce_duplicate_product' ), 10, 2 );
25
+
26
+ //quick & bulk edit
27
+ add_action( 'woocommerce_product_quick_edit_save', array( $this, 'woocommerce_product_quick_edit_save' ) );
28
+ add_action( 'woocommerce_product_bulk_edit_save', array( $this, 'woocommerce_product_quick_edit_save' ) );
29
+
30
+ add_action( 'init', array( $this, 'init' ) );
31
+
32
+ add_action( 'deleted_term_relationships', array( $this, 'delete_term_relationships_update_term_count' ), 10, 2 );
33
+ }
34
+
35
+ add_action( 'woocommerce_reduce_order_stock', array( $this, 'sync_product_stocks_reduce' ) );
36
+ add_action( 'woocommerce_restore_order_stock', array( $this, 'sync_product_stocks_restore' ) );
37
+ add_action( 'woocommerce_product_set_stock_status', array($this, 'sync_stock_status_for_translations' ), 10, 2);
38
+ add_action( 'woocommerce_variation_set_stock_status', array($this, 'sync_stock_status_for_translations' ), 10, 2);
39
+
40
+ add_filter( 'future_product', array( $this, 'set_schedule_for_translations'), 10, 2 );
41
+ }
42
+
43
+ public function init(){
44
+ $this->check_ajax_actions();
45
+ }
46
+
47
+ /**
48
+ * This function takes care of synchronizing products
49
+ */
50
+ public function synchronize_products( $post_id, $post ){
51
+ global $pagenow, $wp;
52
+
53
+ $original_language = $this->woocommerce_wpml->products->get_original_product_language( $post_id );
54
+ $current_language = $this->sitepress->get_current_language();
55
+ $original_product_id = apply_filters( 'translate_object_id', $post_id, 'product', false, $original_language );
56
+
57
+ $wpml_media_options = maybe_unserialize( get_option( '_wpml_media' ) );
58
+
59
+ if( $wpml_media_options[ 'new_content_settings' ][ 'duplicate_media' ] ){
60
+ //sync product gallery
61
+ $this->woocommerce_wpml->media->sync_product_gallery( $original_product_id );
62
+ }
63
+ // check its a product
64
+ $post_type = get_post_type( $post_id );
65
+ //set trid for variations
66
+ if ( $post_type == 'product_variation' ) {
67
+ $var_lang = $this->sitepress->get_language_for_element( wp_get_post_parent_id( $post_id ), 'post_product' );
68
+ if( $this->woocommerce_wpml->products->is_original_product( wp_get_post_parent_id( $post_id ) ) ){
69
+ $this->sitepress->set_element_language_details( $post_id, 'post_product_variation', false, $var_lang );
70
+ }
71
+ }
72
+
73
+ // exceptions
74
+ $ajax_call = ( !empty( $_POST[ 'icl_ajx_action' ] ) && $_POST[ 'icl_ajx_action' ] == 'make_duplicates' );
75
+ $api_call = !empty( $wp->query_vars['wc-api-version'] );
76
+ if (
77
+ $post_type != 'product' ||
78
+ ( empty( $original_product_id ) || isset( $_POST[ 'autosave' ] ) ) ||
79
+ ( $pagenow != 'post.php' && $pagenow != 'post-new.php' && $pagenow != 'admin.php' && !$ajax_call && !$api_call ) ||
80
+ ( isset( $_GET[ 'action' ] ) && $_GET[ 'action' ] == 'trash' )
81
+ ) {
82
+ return;
83
+ }
84
+ // Remove filter to avoid double sync
85
+ remove_action( 'save_post', array( $this, 'synchronize_products' ), 110, 2 );
86
+
87
+ do_action( 'wcml_before_sync_product', $original_product_id, $post_id );
88
+
89
+ //trnsl_interface option
90
+ if ( !$this->woocommerce_wpml->settings['trnsl_interface'] && $original_language != $current_language ) {
91
+ if( !isset( $_POST[ 'wp-preview' ] ) || empty( $_POST[ 'wp-preview' ] ) ){
92
+ //make sure we sync post in current language
93
+ $post_id = apply_filters( 'translate_object_id', $post_id, 'product', false, $current_language );
94
+ $this->sync_product_data( $original_product_id, $post_id, $current_language );
95
+ }
96
+ return;
97
+ }
98
+
99
+ //save files option
100
+ $this->woocommerce_wpml->downloadable->save_files_option( $original_product_id );
101
+ //update products order
102
+ $this->woocommerce_wpml->products->update_order_for_product_translations( $original_product_id );
103
+
104
+ // pick posts to sync
105
+ $trid = $this->sitepress->get_element_trid( $original_product_id, 'post_product' );
106
+ $translations = $this->sitepress->get_element_translations( $trid, 'post_product', false, true );
107
+
108
+ foreach( $translations as $translation ) {
109
+ if ( !$translation->original ) {
110
+ $this->sync_product_data( $original_product_id, $translation->element_id, $translation->language_code );
111
+ }
112
+ }
113
+
114
+ if( $this->woocommerce_wpml->settings[ 'enable_multi_currency' ] == WCML_MULTI_CURRENCIES_INDEPENDENT ) {
115
+ //save custom prices
116
+ $this->woocommerce_wpml->multi_currency->custom_prices->save_custom_prices( $original_product_id );
117
+ $this->woocommerce_wpml->multi_currency->custom_prices->sync_product_variations_custom_prices( $original_product_id );
118
+ }
119
+
120
+ }
121
+
122
+ public function sync_product_data( $original_product_id, $tr_product_id, $lang ){
123
+
124
+ do_action( 'wcml_before_sync_product_data', $original_product_id, $tr_product_id, $lang );
125
+
126
+ $this->duplicate_product_post_meta( $original_product_id, $tr_product_id );
127
+
128
+ $this->sync_date_and_parent( $original_product_id, $tr_product_id, $lang );
129
+
130
+ $this->woocommerce_wpml->attributes->sync_product_attr( $original_product_id, $tr_product_id );
131
+
132
+ $this->woocommerce_wpml->attributes->sync_default_product_attr( $original_product_id, $tr_product_id, $lang );
133
+
134
+ $wpml_media_options = maybe_unserialize( get_option( '_wpml_media' ) );
135
+ //sync media
136
+ if( $wpml_media_options[ 'new_content_settings' ][ 'duplicate_featured' ] ){
137
+ //sync feature image
138
+ $this->woocommerce_wpml->media->sync_thumbnail_id( $original_product_id, $tr_product_id, $lang );
139
+ }
140
+
141
+ //sync taxonomies
142
+ $this->sync_product_taxonomies( $original_product_id, $tr_product_id, $lang );
143
+
144
+ //duplicate variations
145
+
146
+ $this->woocommerce_wpml->sync_variations_data->sync_product_variations( $original_product_id, $tr_product_id, $lang );
147
+
148
+ $this->sync_linked_products( $original_product_id, $tr_product_id, $lang );
149
+
150
+ // Clear any unwanted data
151
+ wc_delete_product_transients( $tr_product_id );
152
+ }
153
+
154
+ public function sync_product_taxonomies( $original_product_id, $tr_product_id, $lang ){
155
+ $taxonomies = get_object_taxonomies( 'product' );
156
+
157
+ foreach( $taxonomies as $taxonomy ) {
158
+
159
+ $terms = wp_get_object_terms( $original_product_id, $taxonomy );
160
+ $tt_ids = array();
161
+ $tt_names = array();
162
+ if ($terms) {
163
+ foreach ($terms as $term) {
164
+ if( $term->taxonomy == 'product_type' ){
165
+ $tt_names[] = $term->name;
166
+ continue;
167
+ }
168
+ $tt_ids[] = $term->term_id;
169
+ }
170
+
171
+ if( $taxonomy == 'product_type' ) {
172
+ wp_set_post_terms( $tr_product_id, $tt_names, $taxonomy );
173
+ }else{
174
+ $this->wcml_update_term_count_by_ids( $tt_ids, $lang, $taxonomy, $tr_product_id );
175
+ }
176
+ }
177
+ }
178
+ }
179
+
180
+ public function delete_term_relationships_update_term_count( $object_id, $tt_ids ){
181
+
182
+ if( get_post_type( $object_id ) == 'product' ){
183
+
184
+ $language_details = $this->sitepress->get_element_language_details( $object_id, 'post_product' );
185
+ $translations = $this->sitepress->get_element_translations( $language_details->trid, 'post_product', false, true );
186
+
187
+ foreach( $translations as $translation ) {
188
+ if ( !$translation->original ) {
189
+ $this->wcml_update_term_count_by_ids( $tt_ids, $translation->language_code );
190
+ }
191
+ }
192
+ }
193
+
194
+ }
195
+ public function wcml_update_term_count_by_ids( $tt_ids, $language, $taxonomy = '', $tr_product_id = false ){
196
+ $terms_array = array();
197
+ $terms_to_insert = array();
198
+
199
+ foreach( $tt_ids as $tt_id ){
200
+
201
+ $tr_id = apply_filters( 'translate_object_id', $tt_id, $taxonomy, false, $language );
202
+
203
+ if( !is_null( $tr_id ) ){
204
+ // not using get_term - unfiltered get_term
205
+ $translated_term = $this->wpdb->get_row( $this->wpdb->prepare( "
206
+ SELECT * FROM {$this->wpdb->terms} t JOIN {$this->wpdb->term_taxonomy} x ON x.term_id = t.term_id WHERE t.term_id = %d", $tr_id ) );
207
+ if( is_taxonomy_hierarchical( $taxonomy ) ){
208
+ $terms_to_insert[] = (int)$translated_term->term_id;
209
+ }else{
210
+ $terms_to_insert[] = $translated_term->slug;
211
+ }
212
+
213
+ $terms_array[] = $translated_term->term_taxonomy_id;
214
+ }
215
+
216
+ }
217
+
218
+
219
+ if( in_array( $taxonomy, array( 'product_cat', 'product_tag' ) ) ) {
220
+ $this->sitepress->switch_lang( $language );
221
+ wp_update_term_count( $terms_array, $taxonomy );
222
+ $this->sitepress->switch_lang( );
223
+ }elseif( $tr_product_id ){
224
+ wp_set_post_terms( $tr_product_id, $terms_to_insert, $taxonomy );
225
+ }
226
+
227
+ }
228
+
229
+ public function sync_linked_products( $product_id, $translated_product_id, $lang ){
230
+ //sync up-sells
231
+ $original_up_sells = maybe_unserialize( get_post_meta( $product_id, '_upsell_ids', true ) );
232
+ $trnsl_up_sells = array();
233
+ if( $original_up_sells ){
234
+ foreach( $original_up_sells as $original_up_sell_product ) {
235
+ $trnsl_up_sells[] = apply_filters( 'translate_object_id', $original_up_sell_product, get_post_type( $original_up_sell_product ), false, $lang );
236
+ }
237
+ }
238
+ update_post_meta( $translated_product_id, '_upsell_ids', $trnsl_up_sells );
239
+ //sync cross-sells
240
+ $original_cross_sells = maybe_unserialize( get_post_meta( $product_id, '_crosssell_ids', true ) );
241
+ $trnsl_cross_sells = array();
242
+ if( $original_cross_sells )
243
+ foreach( $original_cross_sells as $original_cross_sell_product ){
244
+ $trnsl_cross_sells[] = apply_filters( 'translate_object_id', $original_cross_sell_product, get_post_type( $original_cross_sell_product ), false, $lang );
245
+ }
246
+ update_post_meta( $translated_product_id, '_crosssell_ids', $trnsl_cross_sells );
247
+ // refresh parent-children transients (e.g. this child goes to private or draft)
248
+ $translated_product_parent_id = wp_get_post_parent_id( $translated_product_id );
249
+ if ( $translated_product_parent_id ) {
250
+ delete_transient( 'wc_product_children_' . $translated_product_parent_id );
251
+ delete_transient( '_transient_wc_product_children_ids_' . $translated_product_parent_id );
252
+ }
253
+ }
254
+
255
+
256
+
257
+ public function sync_product_stocks_reduce( $order ){
258
+ return $this->sync_product_stocks( $order, 'reduce' );
259
+ }
260
+
261
+ public function sync_product_stocks_restore( $order ){
262
+ return $this->sync_product_stocks( $order, 'restore' );
263
+ }
264
+
265
+ /**
266
+ * @param $order WC_Order
267
+ * @param $action
268
+ */
269
+ public function sync_product_stocks( $order, $action ){
270
+
271
+ foreach( $order->get_items() as $item ) {
272
+
273
+ if( $item instanceof WC_Order_Item_Product ){
274
+ $variation_id = $item->get_variation_id();
275
+ $product_id = $item->get_product_id();
276
+ $qty = $item->get_quantity();
277
+ }else{
278
+ $variation_id = isset( $item[ 'variation_id' ] ) ? $item[ 'variation_id' ] : 0;
279
+ $product_id = $item[ 'product_id' ];
280
+ $qty = $item[ 'qty' ];
281
+ }
282
+
283
+ if( $variation_id > 0 ){
284
+ $trid = $this->sitepress->get_element_trid( $variation_id, 'post_product_variation' );
285
+ $translations = $this->sitepress->get_element_translations( $trid, 'post_product_variation' );
286
+ $ld = $this->sitepress->get_element_language_details( $variation_id, 'post_product_variation' );
287
+ } else {
288
+ $trid = $this->sitepress->get_element_trid( $product_id, 'post_product' );
289
+ $translations = $this->sitepress->get_element_translations( $trid, 'post_product' );
290
+ $ld = $this->sitepress->get_element_language_details( $product_id, 'post_product' );
291
+ }
292
+
293
+ // Process for non-current languages
294
+ foreach( $translations as $translation ){
295
+ if ( $ld->language_code != $translation->language_code ) {
296
+ //check if product exist
297
+ if( get_post_type( $translation->element_id ) == 'product_variation' && !get_post( wp_get_post_parent_id( $translation->element_id ) ) ){
298
+ continue;
299
+ }
300
+ $_product = wc_get_product( $translation->element_id );
301
+
302
+ if( $_product && $_product->exists() && $_product->managing_stock() ) {
303
+ $total_sales = get_post_meta( $translation->element_id, 'total_sales', true);
304
+
305
+ if( $action == 'reduce'){
306
+ $stock = Deprecated_WC_Functions::reduce_stock( $translation->element_id, $qty );
307
+ $total_sales += $qty;
308
+ }else{
309
+ $stock = Deprecated_WC_Functions::increase_stock( $translation->element_id, $qty );
310
+ $total_sales -= $qty;
311
+ }
312
+ update_post_meta( $translation->element_id, 'total_sales', $total_sales );
313
+ }
314
+ }
315
+ }
316
+ }
317
+ }
318
+
319
+ public function sync_stock_status_for_translations( $id, $status ){
320
+
321
+ $type = get_post_type( $id );
322
+ $trid = $this->sitepress->get_element_trid( $id, 'post_'.$type );
323
+ $translations = $this->sitepress->get_element_translations( $trid, 'post_'.$type, true);
324
+
325
+ foreach ( $translations as $translation ) {
326
+ if ( !$translation->original ) {
327
+ update_post_meta( $translation->element_id, '_stock_status', $status );
328
+ }
329
+ }
330
+ }
331
+
332
+ //sync product parent & post_status
333
+ public function sync_date_and_parent( $duplicated_post_id, $post_id, $lang ){
334
+ $tr_parent_id = apply_filters( 'translate_object_id', wp_get_post_parent_id( $duplicated_post_id ), 'product', false, $lang );
335
+ $orig_product = get_post( $duplicated_post_id );
336
+ $args = array();
337
+ $args[ 'post_parent' ] = is_null( $tr_parent_id )? 0 : $tr_parent_id;
338
+ //sync product date
339
+
340
+ if( !empty( $this->woocommerce_wpml->settings[ 'products_sync_date' ] ) ){
341
+ $args[ 'post_date' ] = $orig_product->post_date;
342
+ }
343
+ $this->wpdb->update(
344
+ $this->wpdb->posts,
345
+ $args,
346
+ array( 'id' => $post_id )
347
+ );
348
+ }
349
+
350
+ public function set_schedule_for_translations( $deprecated, $post ){
351
+
352
+ if( $this->woocommerce_wpml->products->is_original_product( $post->ID ) ) {
353
+ $trid = $this->sitepress->get_element_trid( $post->ID, 'post_product');
354
+ $translations = $this->sitepress->get_element_translations( $trid, 'post_product', true);
355
+ foreach( $translations as $translation ) {
356
+ if( !$translation->original ){
357
+ wp_clear_scheduled_hook( 'publish_future_post', array( $translation->element_id ) );
358
+ wp_schedule_single_event( strtotime( get_gmt_from_date( $post->post_date) . ' GMT' ), 'publish_future_post', array( $translation->element_id ) );
359
+ }
360
+ }
361
+ }
362
+ }
363
+
364
+
365
+
366
+ public function icl_pro_translation_completed( $tr_product_id ){
367
+ $trid = $this->sitepress->get_element_trid( $tr_product_id, 'post_product' );
368
+ $translations = $this->sitepress->get_element_translations( $trid, 'post_product' );
369
+
370
+ foreach( $translations as $translation ){
371
+ if( $translation->original ){
372
+ $original_product_id = $translation->element_id;
373
+ }
374
+ }
375
+
376
+ if( !isset( $original_product_id ) ){
377
+ return;
378
+ }
379
+
380
+ $lang = $this->sitepress->get_language_for_element( $tr_product_id, 'post_product' );
381
+ $this->sync_product_data( $original_product_id, $tr_product_id, $lang );
382
+ }
383
+
384
+ public function icl_make_duplicate( $master_post_id, $lang, $postarr, $id ){
385
+ if( get_post_type( $master_post_id ) == 'product' ){
386
+
387
+ $original_language = $this->woocommerce_wpml->products->get_original_product_language( $master_post_id );
388
+ $master_post_id = apply_filters( 'translate_object_id', $master_post_id, 'product', false, $original_language );
389
+
390
+ $this->sync_product_data( $master_post_id, $id, $lang );
391
+ }
392
+ }
393
+
394
+ public function woocommerce_product_quick_edit_save( $product ){
395
+ $is_original = $this->woocommerce_wpml->products->is_original_product( $product->id );
396
+ $trid = $this->sitepress->get_element_trid( $product->id, 'post_product' );
397
+
398
+ if( $trid ){
399
+ $translations = $this->sitepress->get_element_translations( $trid, 'post_product' );
400
+ if( $translations ){
401
+ foreach( $translations as $translation ){
402
+ if( $is_original ){
403
+ if( !$translation->original ){
404
+ $this->sync_product_data( $product->id, $translation->element_id, $translation->language_code );
405
+ $this->sync_date_and_parent( $product->id, $translation->element_id, $translation->language_code );
406
+ }
407
+ }elseif( $translation->original ){
408
+ $this->sync_product_data( $translation->element_id, $product->id, $this->sitepress->get_language_for_element( $product->id, 'post_product' ) );
409
+ $this->sync_date_and_parent( $translation->element_id, $product->id, $this->sitepress->get_language_for_element( $product->id, 'post_product' ) );
410
+ }
411
+ }
412
+ }
413
+ }
414
+ }
415
+
416
+ //duplicate product post meta
417
+ public function duplicate_product_post_meta( $original_product_id, $trnsl_product_id, $data = false ){
418
+ global $iclTranslationManagement;
419
+
420
+ if( $this->check_if_product_fields_sync_needed( $original_product_id, 'postmeta_fields' ) ){
421
+ $settings = $iclTranslationManagement->settings[ 'custom_fields_translation' ];
422
+ $all_meta = get_post_custom( $original_product_id );
423
+ $post_fields = null;
424
+
425
+ unset( $all_meta[ '_thumbnail_id' ] );
426
+
427
+ foreach ( $all_meta as $key => $meta ) {
428
+ if ( !isset( $settings[ $key ] ) || $settings[ $key ] == WPML_IGNORE_CUSTOM_FIELD ) {
429
+ continue;
430
+ }
431
+ foreach ( $meta as $meta_value ) {
432
+ if( $key == '_downloadable_files' ){
433
+ $this->woocommerce_wpml->downloadable->sync_files_to_translations( $original_product_id, $trnsl_product_id, $data );
434
+ }elseif ( $data ) {
435
+ if ( isset( $settings[ $key ] ) && $settings[ $key ] == WPML_TRANSLATE_CUSTOM_FIELD ) {
436
+
437
+ $post_fields = $this->sync_custom_field_value( $key, $data, $trnsl_product_id, $post_fields );
438
+ }
439
+ }
440
+ }
441
+ }
442
+ }
443
+
444
+ do_action( 'wcml_after_duplicate_product_post_meta', $original_product_id, $trnsl_product_id, $data );
445
+ }
446
+
447
+ public function sync_custom_field_value( $custom_field, $translation_data, $trnsl_product_id, $post_fields, $original_product_id = false, $is_variation = false ){
448
+
449
+ if( is_null( $post_fields ) ){
450
+ $post_fields = array();
451
+ if( isset( $_POST['data'] ) ){
452
+ $post_args = wp_parse_args( $_POST['data'] );
453
+ $post_fields = $post_args[ 'fields' ];
454
+ }
455
+ }
456
+
457
+ $custom_filed_key = $is_variation && $original_product_id ? $custom_field.$original_product_id : $custom_field;
458
+
459
+ if( isset( $translation_data[ md5( $custom_filed_key ) ] ) ){
460
+ $meta_value = $translation_data[ md5( $custom_filed_key ) ];
461
+ $meta_value = apply_filters( 'wcml_meta_value_before_add', $meta_value, $custom_filed_key );
462
+ update_post_meta( $trnsl_product_id, $custom_field, $meta_value );
463
+ unset( $post_fields[ $custom_filed_key ] );
464
+ }else{
465
+ foreach( $post_fields as $post_field_key => $post_field ){
466
+ $meta_value = $translation_data[ md5( $post_field_key ) ];
467
+ $field_key = explode( ':', $post_field_key );
468
+ if( $field_key[0] == $custom_filed_key ){
469
+ if( substr( $field_key[1], 0, 3 ) == 'new' ){
470
+ add_post_meta( $trnsl_product_id, $custom_field, $meta_value );
471
+ }else{
472
+ update_meta( $field_key[1], $custom_field, $meta_value );
473
+ }
474
+ unset( $post_fields[ $post_field_key ] );
475
+ }
476
+ }
477
+ }
478
+
479
+ return $post_fields;
480
+ }
481
+
482
+ public function woocommerce_duplicate_product( $new_id, $post ){
483
+ $duplicated_products = array();
484
+
485
+ //duplicate original first
486
+ $trid = $this->sitepress->get_element_trid( $post->ID, 'post_' . $post->post_type );
487
+ $orig_id = $this->sitepress->get_original_element_id_by_trid( $trid );
488
+ $orig_lang = $this->woocommerce_wpml->products->get_original_product_language( $post->ID );
489
+
490
+ $wc_admin = new WC_Admin_Duplicate_Product();
491
+
492
+ if( $orig_id == $post->ID ){
493
+ $this->sitepress->set_element_language_details( $new_id, 'post_' . $post->post_type, false, $orig_lang );
494
+ $new_trid = $this->sitepress->get_element_trid( $new_id, 'post_' . $post->post_type );
495
+ $new_orig_id = $new_id;
496
+ }else{
497
+ $post_to_duplicate = $this->wpdb->get_row( $this->wpdb->prepare( "SELECT * FROM {$this->wpdb->posts} WHERE ID=%d", $orig_id ) );
498
+ if ( ! empty( $post_to_duplicate ) ) {
499
+ $new_orig_id = $wc_admin->duplicate_product( $post_to_duplicate );
500
+ do_action( 'wcml_after_duplicate_product' , $new_id, $post_to_duplicate );
501
+ $this->sitepress->set_element_language_details( $new_orig_id, 'post_' . $post->post_type, false, $orig_lang );
502
+ $new_trid = $this->sitepress->get_element_trid( $new_orig_id, 'post_' . $post->post_type );
503
+ if( get_post_meta( $orig_id, '_icl_lang_duplicate_of' ) ){
504
+ update_post_meta( $new_id, '_icl_lang_duplicate_of', $new_orig_id );
505
+ }
506
+ $this->sitepress->set_element_language_details( $new_id, 'post_' . $post->post_type, $new_trid, $this->sitepress->get_current_language() );
507
+ }
508
+ }
509
+
510
+ // Set language info for variations
511
+ if ( $children_products = get_children( 'post_parent=' . $new_orig_id . '&post_type=product_variation' ) ) {
512
+ foreach ( $children_products as $child ) {
513
+ $this->sitepress->set_element_language_details( $child->ID, 'post_product_variation', false, $orig_lang );
514
+ }
515
+ }
516
+
517
+ $translations = $this->sitepress->get_element_translations( $trid, 'post_' . $post->post_type );
518
+ $duplicated_products[ 'translations' ] = array();
519
+ if( $translations ){
520
+ foreach( $translations as $translation ){
521
+ if( !$translation->original && $translation->element_id != $post->ID ){
522
+ $post_to_duplicate = $this->wpdb->get_row( $this->wpdb->prepare( "SELECT * FROM {$this->wpdb->posts} WHERE ID=%d", $translation->element_id ) );
523
+
524
+ if( ! empty( $post_to_duplicate ) ) {
525
+ $new_id = $wc_admin->duplicate_product( $post_to_duplicate );
526
+ $new_id_obj = get_post( $new_id );
527
+ $new_slug = wp_unique_post_slug( sanitize_title( $new_id_obj->post_title ), $new_id, $post_to_duplicate->post_status, $post_to_duplicate->post_type, $new_id_obj->post_parent );
528
+
529
+ $this->wpdb->update(
530
+ $this->wpdb->posts,
531
+ array(
532
+ 'post_name' => $new_slug,
533
+ 'post_status' => 'draft'
534
+ ),
535
+ array( 'ID' => $new_id )
536
+ );
537
+
538
+ do_action( 'wcml_after_duplicate_product' , $new_id, $post_to_duplicate );
539
+ $this->sitepress->set_element_language_details( $new_id, 'post_' . $post->post_type, $new_trid, $translation->language_code );
540
+ if( get_post_meta( $translation->element_id, '_icl_lang_duplicate_of' ) ){
541
+ update_post_meta( $new_id, '_icl_lang_duplicate_of', $new_orig_id );
542
+ }
543
+ $duplicated_products[ 'translations' ][] = $new_id;
544
+ }
545
+ }
546
+ }
547
+ }
548
+
549
+ $duplicated_products[ 'original' ] = $new_orig_id;
550
+
551
+ return $duplicated_products;
552
+ }
553
+
554
+ public function check_ajax_actions(){
555
+ if( isset( $_POST[ 'icl_ajx_action' ] ) && $_POST[ 'icl_ajx_action' ] == 'connect_translations' ){
556
+ $this->icl_connect_translations_action();
557
+ }
558
+ }
559
+
560
+ public function icl_connect_translations_action(){
561
+ $new_trid = $_POST['new_trid'];
562
+ $post_type = $_POST['post_type'];
563
+ $post_id = $_POST['post_id'];
564
+ $set_as_source = $_POST['set_as_source'];
565
+ if( $post_type == 'product' ){
566
+
567
+ $translations = $this->sitepress->get_element_translations( $new_trid, 'post_' . $post_type );
568
+ if( $translations ) {
569
+ foreach ( $translations as $translation ) {
570
+ //current as original need sync translation
571
+ if ( $translation->original ) {
572
+ if( $set_as_source ) {
573
+ $orig_id = $post_id;
574
+ $trnsl_id = $translation->element_id;
575
+ $lang = $translation->language_code;
576
+ }else{
577
+ $orig_id = $translation->element_id;
578
+ $trnsl_id = $post_id;
579
+ $lang = $this->sitepress->get_current_language();
580
+ }
581
+ $this->sync_product_data( $orig_id, $trnsl_id, $lang );
582
+ $this->sync_date_and_parent( $orig_id, $trnsl_id, $lang );
583
+ $this->sitepress->copy_custom_fields( $orig_id, $trnsl_id );
584
+ }else {
585
+ if( $set_as_source ) {
586
+ $this->sync_product_data( $post_id, $translation->element_id, $translation->language_code );
587
+ $this->sync_date_and_parent( $post_id, $translation->element_id, $translation->language_code );
588
+ $this->sitepress->copy_custom_fields( $post_id, $translation->element_id );
589
+ }
590
+ }
591
+ }
592
+ }
593
+ }
594
+ }
595
+
596
+ public function check_if_product_fields_sync_needed( $original_id, $fields_group ){
597
+
598
+ $cache_group = 'is_product_fields_sync_needed';
599
+ $cache_key = $original_id.$fields_group;
600
+ $temp_is_sync_needed = wp_cache_get( $cache_key, $cache_group );
601
+
602
+ if( $temp_is_sync_needed !== false ) return boolval( $temp_is_sync_needed );
603
+
604
+ $is_sync_needed = true;
605
+ $hash = '';
606
+
607
+ switch( $fields_group ){
608
+ case 'postmeta_fields':
609
+ $custom_fields = get_post_custom( $original_id );
610
+ unset( $custom_fields[ 'wcml_sync_hash' ] );
611
+ $hash = md5( serialize( $custom_fields ) );
612
+ break;
613
+ case 'taxonomies':
614
+ $all_taxs = get_object_taxonomies( get_post_type( $original_id ) );
615
+ $taxs = array();
616
+
617
+ if ( !empty( $all_taxs ) ) {
618
+ foreach ($all_taxs as $tt) {
619
+ $terms = get_the_terms( $original_id, $tt );
620
+ if( !empty( $terms ) ) {
621
+ foreach ( $terms as $term ) {
622
+ $taxs[] = $term->term_id;
623
+ }
624
+ }
625
+ }
626
+ }
627
+
628
+ $hash = md5( join( ',', $taxs ) );
629
+ break;
630
+ case 'default_attributes':
631
+ $hash = md5( get_post_meta( $original_id, '_default_attributes', true ) );
632
+ break;
633
+ }
634
+
635
+ $post_md5 = maybe_unserialize( get_post_meta( $original_id, 'wcml_sync_hash', true ) );
636
+
637
+ if( isset( $post_md5[ $fields_group ] ) && $post_md5[ $fields_group ] == $hash ){
638
+ $is_sync_needed = false;
639
+ }else{
640
+ $post_md5[ $fields_group ] = $hash;
641
+ update_post_meta( $original_id, 'wcml_sync_hash', $post_md5 );
642
+ }
643
+
644
+ wp_cache_set( $cache_key, intval( $is_sync_needed ), $cache_group );
645
+
646
+ return $is_sync_needed;
647
+ }
648
+
649
  }
inc/translation-editor/class-wcml-synchronize-variations-data.php CHANGED
@@ -25,7 +25,7 @@ class WCML_Synchronize_Variations_Data{
25
  if( $this->woocommerce_wpml->products->is_original_product( $product_id ) ){
26
 
27
  if( $this->woocommerce_wpml->settings['enable_multi_currency'] == WCML_MULTI_CURRENCIES_INDEPENDENT ) {
28
- $this->woocommerce_wpml->multi_currency->custom_prices->sync_product_variations_custom_prices($product_id);
29
  }
30
  $trid = $this->sitepress->get_element_trid( $product_id, 'post_product' );
31
 
@@ -41,7 +41,7 @@ class WCML_Synchronize_Variations_Data{
41
  foreach ( $translations as $translation ) {
42
  if ( !$translation->original ) {
43
  $this->sync_product_variations($product_id, $translation->element_id, $translation->language_code);
44
- $this->woocommerce_wpml->attributes->sync_default_product_attr($product_id, $translation->element_id, $translation->language_code);
45
  }
46
  }
47
  }
@@ -55,71 +55,33 @@ class WCML_Synchronize_Variations_Data{
55
  * $data - array of values (when we save original product this array is empty, but when we update translation in this array we have price values and etc.) *
56
  * */
57
  public function sync_product_variations( $product_id, $tr_product_id, $lang, $data = false, $trbl = false ){
58
- global $sitepress_settings, $wpml_post_translations;
59
 
60
- remove_action ( 'save_post', array( $wpml_post_translations, 'save_post_actions' ), 100, 2 );
61
  $is_variable_product = $this->woocommerce_wpml->products->is_variable_product( $product_id );
62
 
63
  if( $is_variable_product ){
64
- $get_all_post_variations = $this->wpdb->get_results(
65
- $this->wpdb->prepare(
66
- "SELECT * FROM {$this->wpdb->posts}
67
- WHERE post_status IN ('publish','private')
68
- AND post_type = 'product_variation'
69
- AND post_parent = %d ORDER BY ID",
70
- $product_id )
71
- );
72
- $duplicated_post_variation_ids = array();
73
- $min_max_prices = array();
74
-
75
- foreach( $get_all_post_variations as $k => $post_data ){
76
- $duplicated_post_variation_ids[] = $post_data->ID;
77
- }
78
 
79
- foreach( $min_max_prices as $price_key => $min_max_price ){
80
- update_post_meta( $product_id, $price_key, $min_max_price );
81
- }
82
- $all_taxs = get_object_taxonomies( 'product_variation' );
83
 
84
- foreach( $get_all_post_variations as $k => $post_data ) {
85
  $original_variation_id = $post_data->ID;
86
 
87
- // Find if this has already been duplicated
88
- $variation_id = $this->wpdb->get_var(
89
- $this->wpdb->prepare(
90
- "SELECT post_id FROM {$this->wpdb->postmeta} AS pm
91
- JOIN {$this->wpdb->prefix}icl_translations AS tr ON tr.element_id = pm.post_id
92
- WHERE tr.element_type = 'post_product_variation'
93
- AND tr.language_code = %s
94
- AND pm.meta_key = '_wcml_duplicate_of_variation'
95
- AND pm.meta_value = %d",
96
- $lang, $original_variation_id )
97
- );
98
- $trid = $this->sitepress->get_element_trid( $original_variation_id, 'post_product_variation' );
99
  if( !empty( $variation_id ) && !is_null( $variation_id ) ) {
 
 
100
  // Update variation
101
  wp_update_post( array(
102
  'ID' => $variation_id,
103
- 'post_author' => $post_data->post_author,
104
- 'post_date_gmt' => $post_data->post_date_gmt,
105
- 'post_content' => $post_data->post_content,
106
- 'post_title' => $post_data->post_title,
107
- 'post_excerpt' => $post_data->post_excerpt,
108
  'post_status' => $post_data->post_status,
109
- 'comment_status' => $post_data->comment_status,
110
- 'ping_status' => $post_data->ping_status,
111
- 'post_password' => $post_data->post_password,
112
- 'post_name' => $post_data->post_name,
113
- 'to_ping' => $post_data->to_ping,
114
- 'pinged' => $post_data->pinged,
115
  'post_modified' => $post_data->post_modified,
116
  'post_modified_gmt' => $post_data->post_modified_gmt,
117
- 'post_content_filtered' => $post_data->post_content_filtered,
118
  'post_parent' => $tr_product_id, // current post ID
119
  'menu_order' => $post_data->menu_order,
120
- 'post_type' => $post_data->post_type,
121
- 'post_mime_type' => $post_data->post_mime_type,
122
- 'comment_count' => $post_data->comment_count
123
  ));
124
  } else {
125
  // Add new variation
@@ -151,115 +113,118 @@ class WCML_Synchronize_Variations_Data{
151
  'comment_count' => $post_data->comment_count
152
  ));
153
  add_post_meta( $variation_id, '_wcml_duplicate_of_variation', $original_variation_id );
 
154
  $this->sitepress->set_element_language_details( $variation_id, 'post_product_variation', $trid, $lang );
155
  }
156
- //sync media
157
- $this->woocommerce_wpml->media->sync_thumbnail_id( $original_variation_id, $variation_id, $lang );
158
- //sync file_paths
159
- $this->woocommerce_wpml->downloadable->sync_files_to_translations( $original_variation_id, $variation_id, $data );
160
  //sync description
161
  if( isset( $data[ md5( '_variation_description'.$original_variation_id ) ] ) ){
162
  update_post_meta( $variation_id, '_variation_description', $data[ md5( '_variation_description'.$original_variation_id ) ] );
163
  }
164
- // sync taxonomies
165
- if ( !empty( $all_taxs ) ) {
166
- foreach ( $all_taxs as $tt ) {
167
- $terms = get_the_terms( $original_variation_id, $tt );
168
- if ( !empty( $terms ) ) {
169
- $tax_sync = array();
170
- foreach ( $terms as $term ) {
171
- if ( $this->sitepress->is_translated_taxonomy( $tt ) ) {
172
- $term_id = apply_filters( 'translate_object_id', $term->term_id, $tt, false, $lang );
173
- } else {
174
- $term_id = $term->term_id;
175
- }
176
- if ( $term_id ) {
177
- $tax_sync[] = intval( $term_id );
178
- }
179
- }
180
- //set the fourth parameter in 'true' because we need to add new terms, instead of replacing all
181
- wp_set_object_terms( $variation_id, $tax_sync, $tt, true );
182
- }
183
- }
184
- }
185
  }
186
- $get_current_post_variations = $this->wpdb->get_results(
187
- $this->wpdb->prepare(
188
- "SELECT * FROM {$this->wpdb->posts}
189
- WHERE post_status IN ('publish','private')
190
- AND post_type = 'product_variation'
191
- AND post_parent = %d ORDER BY ID",
192
- $tr_product_id )
193
- );
194
  // Delete variations that no longer exist
195
- foreach( $get_current_post_variations as $key => $current_post_variation ){
196
- $orig_variation_id = get_post_meta( $current_post_variation->ID, '_wcml_duplicate_of_variation', true );
197
- if( !in_array( $orig_variation_id, $duplicated_post_variation_ids ) ){
198
- wp_delete_post( $current_post_variation->ID, true );
199
- unset( $get_current_post_variations[ $key ] );
200
- }
201
  }
202
- // custom fields to copy
203
- $cf = (array)$sitepress_settings[ 'translation-management' ][ 'custom_fields_translation' ];
204
- // synchronize post variations post meta
205
- $current_post_variation_ids = array();
206
- foreach( $get_current_post_variations as $k => $current_post_variation ){
207
- $current_post_variation_ids[] = $current_post_variation->ID;
208
- }
209
- // refresh parent-children transients
210
- delete_transient( 'wc_product_children_' . $tr_product_id );
211
- delete_transient( '_transient_wc_product_children_ids_' . $tr_product_id );
212
- $original_product_attr = get_post_meta( $product_id, '_product_attributes', true );
213
- $tr_product_attr = get_post_meta( $tr_product_id, '_product_attributes', true );
214
-
215
- foreach( $duplicated_post_variation_ids as $dp_key => $duplicated_post_variation_id ){
216
- $get_all_post_meta = $this->wpdb->get_results(
217
- $this->wpdb->prepare(
218
- "SELECT * FROM {$this->wpdb->postmeta} WHERE post_id = %d",
219
- $duplicated_post_variation_id )
220
- );
221
- //delete non exists attributes
222
- $get_all_variation_attributes = $this->wpdb->get_results(
223
- $this->wpdb->prepare(
224
- "SELECT * FROM {$this->wpdb->postmeta}
225
- WHERE post_id = %d
226
- AND meta_key LIKE 'attribute_%%' ",
227
- $current_post_variation_ids[ $dp_key ] )
228
- );
229
- foreach( $get_all_variation_attributes as $variation_attribute ){
230
- $attribute_name = substr( $variation_attribute->meta_key, 10 );
231
- if( !isset( $original_product_attr[ $attribute_name ] ) ){
232
- delete_post_meta( $current_post_variation_ids[ $dp_key ], $variation_attribute->meta_key );
 
 
 
 
 
 
 
 
 
 
233
  }
234
  }
 
 
 
235
 
236
- $post_fields = null;
237
- foreach( $get_all_post_meta as $k => $post_meta ){
238
 
239
- $meta_key = $post_meta->meta_key;
240
- $meta_value = maybe_unserialize( $post_meta->meta_value );
 
 
 
 
 
 
 
241
  // update current post variations meta
242
- if( ( substr( $meta_key, 0, 10 ) == 'attribute_' || isset( $cf[ $meta_key ] ) && $cf[ $meta_key ] == 1 ) ) {
 
 
243
  // adjust the global attribute slug in the custom field
244
  $attid = null;
245
  if( substr( $meta_key, 0, 10 ) == 'attribute_' ) {
 
 
 
 
246
  $tax = wc_sanitize_taxonomy_name ( substr( $meta_key, 10 ) );
247
  if( taxonomy_exists( $tax ) ){
248
  $attid = $this->woocommerce_wpml->terms->wcml_get_term_id_by_slug( $tax, $meta_value );
249
  if( $this->woocommerce_wpml->attributes->is_translatable_attribute( $tax ) && $attid ){
 
250
  $term_obj = $this->woocommerce_wpml->terms->wcml_get_term_by_id( $attid, $tax );
251
- $trid = $this->sitepress->get_element_trid( $term_obj->term_taxonomy_id, 'tax_' . $tax );
252
- if( $trid ) {
253
- $translations = $this->sitepress->get_element_translations( $trid, 'tax_' . $tax );
254
- if( isset( $translations[ $lang ] ) ){
255
- $meta_value = $this->wpdb->get_var(
256
- $this->wpdb->prepare(
257
- "SELECT slug FROM {$this->wpdb->terms} WHERE term_id = %s",
258
- $translations[ $lang ]->term_id )
259
- );
260
- }else{
261
- $meta_value = $meta_value.'_'.$lang;
262
- }
263
  }
264
  }
265
  }else{
@@ -283,33 +248,71 @@ class WCML_Synchronize_Variations_Data{
283
  $meta_value = $values_arrs_tr[ $key ];
284
  }
285
  }
286
- }else{
287
- $meta_value = $meta_value.'_'.$lang;
288
  }
289
  }
290
  $meta_key = 'attribute_'.$tax;
291
  }
292
-
293
  }
294
- update_post_meta( $current_post_variation_ids[ $dp_key ], $meta_key, $meta_value );
 
 
295
  }
 
296
  //sync variation prices
297
  if(
298
  ( $this->woocommerce_wpml->settings[ 'enable_multi_currency' ] == WCML_MULTI_CURRENCIES_INDEPENDENT || $trbl ) &&
299
  in_array( $meta_key, array( '_sale_price', '_regular_price', '_price' ) )
300
  ){
301
- $meta_value = get_post_meta( $duplicated_post_variation_ids[ $dp_key ], $meta_key, true );
302
- update_post_meta( $current_post_variation_ids[ $dp_key ], $meta_key, $meta_value );
303
  }
304
 
305
- if( isset( $cf[ $meta_key ] ) && $cf[ $meta_key ] == WPML_TRANSLATE_CUSTOM_FIELD ){
306
  //sync custom fields
307
  $post_fields = $this->woocommerce_wpml->sync_product_data->sync_custom_field_value( $meta_key, $data, $variation_id, $post_fields, $original_variation_id, true );
308
  }
309
  }
310
  }
311
  }
312
- add_action ( 'save_post', array( $wpml_post_translations, 'save_post_actions' ), 100, 2 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
313
  }
314
 
315
  public function remove_translations_for_variations(){
25
  if( $this->woocommerce_wpml->products->is_original_product( $product_id ) ){
26
 
27
  if( $this->woocommerce_wpml->settings['enable_multi_currency'] == WCML_MULTI_CURRENCIES_INDEPENDENT ) {
28
+ $this->woocommerce_wpml->multi_currency->custom_prices->sync_product_variations_custom_prices( $product_id );
29
  }
30
  $trid = $this->sitepress->get_element_trid( $product_id, 'post_product' );
31
 
41
  foreach ( $translations as $translation ) {
42
  if ( !$translation->original ) {
43
  $this->sync_product_variations($product_id, $translation->element_id, $translation->language_code);
44
+ $this->woocommerce_wpml->attributes->sync_default_product_attr( $product_id, $translation->element_id, $translation->language_code );
45
  }
46
  }
47
  }
55
  * $data - array of values (when we save original product this array is empty, but when we update translation in this array we have price values and etc.) *
56
  * */
57
  public function sync_product_variations( $product_id, $tr_product_id, $lang, $data = false, $trbl = false ){
58
+ global $wpml_post_translations;
59
 
 
60
  $is_variable_product = $this->woocommerce_wpml->products->is_variable_product( $product_id );
61
 
62
  if( $is_variable_product ){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
 
64
+ remove_action ( 'save_post', array( $wpml_post_translations, 'save_post_actions' ), 100, 2 );
65
+
66
+ $all_variations = $this->get_product_variations( $product_id );
67
+ $current_variations = $this->get_product_variations( $tr_product_id );
68
 
69
+ foreach( $all_variations as $key => $post_data ) {
70
  $original_variation_id = $post_data->ID;
71
 
72
+ $variation_id = $this->get_variation_id_by_lang( $lang, $original_variation_id );
73
+
 
 
 
 
 
 
 
 
 
 
74
  if( !empty( $variation_id ) && !is_null( $variation_id ) ) {
75
+ //unset variation from array to delete variations that no longer exist
76
+ unset( $current_variations[ $key ] );
77
  // Update variation
78
  wp_update_post( array(
79
  'ID' => $variation_id,
 
 
 
 
 
80
  'post_status' => $post_data->post_status,
 
 
 
 
 
 
81
  'post_modified' => $post_data->post_modified,
82
  'post_modified_gmt' => $post_data->post_modified_gmt,
 
83
  'post_parent' => $tr_product_id, // current post ID
84
  'menu_order' => $post_data->menu_order,
 
 
 
85
  ));
86
  } else {
87
  // Add new variation
113
  'comment_count' => $post_data->comment_count
114
  ));
115
  add_post_meta( $variation_id, '_wcml_duplicate_of_variation', $original_variation_id );
116
+ $trid = $this->sitepress->get_element_trid( $original_variation_id, 'post_product_variation' );
117
  $this->sitepress->set_element_language_details( $variation_id, 'post_product_variation', $trid, $lang );
118
  }
119
+
 
 
 
120
  //sync description
121
  if( isset( $data[ md5( '_variation_description'.$original_variation_id ) ] ) ){
122
  update_post_meta( $variation_id, '_variation_description', $data[ md5( '_variation_description'.$original_variation_id ) ] );
123
  }
124
+
125
+ //sync media
126
+ $this->woocommerce_wpml->media->sync_thumbnail_id( $original_variation_id, $variation_id, $lang );
127
+ //sync file_paths
128
+ $this->woocommerce_wpml->downloadable->sync_files_to_translations( $original_variation_id, $variation_id, $data );
129
+
130
+ //sync taxonomies
131
+ $this->sync_variations_taxonomies( $original_variation_id, $variation_id, $lang );
132
+
133
+ $this->duplicate_variation_data( $original_variation_id, $variation_id, $data, $lang, $trbl );
134
+
135
+ $this->delete_removed_variation_attributes( $product_id, $variation_id );
136
+
137
+ //refresh parent-children transients
138
+ delete_transient( 'wc_product_children_' . $tr_product_id );
139
+ delete_transient( '_transient_wc_product_children_ids_' . $tr_product_id );
140
+
 
 
 
 
141
  }
142
+
 
 
 
 
 
 
 
143
  // Delete variations that no longer exist
144
+ foreach( $current_variations as $key => $current_post_variation ){
145
+ wp_delete_post( $current_post_variation->ID, true );
 
 
 
 
146
  }
147
+
148
+ add_action ( 'save_post', array( $wpml_post_translations, 'save_post_actions' ), 100, 2 );
149
+ }
150
+ }
151
+
152
+ public function get_variation_id_by_lang( $lang, $original_variation_id ){
153
+ return $this->wpdb->get_var(
154
+ $this->wpdb->prepare(
155
+ "SELECT post_id FROM {$this->wpdb->postmeta} AS pm
156
+ JOIN {$this->wpdb->prefix}icl_translations AS tr ON tr.element_id = pm.post_id
157
+ WHERE tr.element_type = 'post_product_variation'
158
+ AND tr.language_code = %s
159
+ AND pm.meta_key = '_wcml_duplicate_of_variation'
160
+ AND pm.meta_value = %d",
161
+ $lang, $original_variation_id )
162
+ );
163
+ }
164
+
165
+ public function sync_variations_taxonomies( $original_variation_id, $tr_variation_id, $lang ){
166
+ if( $this->woocommerce_wpml->sync_product_data->check_if_product_fields_sync_needed( $original_variation_id, 'taxonomies' ) ){
167
+ $all_taxs = get_object_taxonomies( 'product_variation' );
168
+
169
+ $tr_product_attr = get_post_meta( $tr_variation_id, '_product_attributes', true );
170
+
171
+ if ( !empty( $all_taxs ) ) {
172
+ foreach ( $all_taxs as $tt ) {
173
+ $terms = get_the_terms( $original_variation_id, $tt );
174
+ if ( !empty( $terms ) ) {
175
+ $tax_sync = array();
176
+ foreach ( $terms as $term ) {
177
+ if ( $this->sitepress->is_translated_taxonomy( $tt ) ) {
178
+ $term_id = apply_filters( 'translate_object_id', $term->term_id, $tt, false, $lang );
179
+ } else {
180
+ $term_id = $term->term_id;
181
+ }
182
+ if ( $term_id ) {
183
+ $tax_sync[] = intval( $term_id );
184
+ }
185
+ }
186
+ //set the fourth parameter in 'true' because we need to add new terms, instead of replacing all
187
+ wp_set_object_terms( $tr_variation_id, $tax_sync, $tt, true );
188
  }
189
  }
190
+ }
191
+ }
192
+ }
193
 
194
+ public function duplicate_variation_data( $original_variation_id, $variation_id, $data, $lang, $trbl ){
195
+ global $iclTranslationManagement;
196
 
197
+ if( $this->woocommerce_wpml->sync_product_data->check_if_product_fields_sync_needed( $original_variation_id, 'postmeta_fields' ) ){
198
+ // custom fields
199
+ $settings = $iclTranslationManagement->settings[ 'custom_fields_translation' ];
200
+ $all_meta = get_post_custom( $original_variation_id );
201
+
202
+ $post_fields = null;
203
+ foreach( $all_meta as $meta_key => $meta ){
204
+
205
+ foreach ( $meta as $meta_value ) {
206
  // update current post variations meta
207
+
208
+ if( ( substr( $meta_key, 0, 10 ) == 'attribute_' || isset( $settings[ $meta_key ] ) && $settings[ $meta_key ] == WPML_COPY_CUSTOM_FIELD ) ) {
209
+
210
  // adjust the global attribute slug in the custom field
211
  $attid = null;
212
  if( substr( $meta_key, 0, 10 ) == 'attribute_' ) {
213
+
214
+ $original_product_attr = get_post_meta( wp_get_post_parent_id( $original_variation_id ), '_product_attributes', true );
215
+ $tr_product_attr = get_post_meta( wp_get_post_parent_id( $variation_id ), '_product_attributes', true );
216
+
217
  $tax = wc_sanitize_taxonomy_name ( substr( $meta_key, 10 ) );
218
  if( taxonomy_exists( $tax ) ){
219
  $attid = $this->woocommerce_wpml->terms->wcml_get_term_id_by_slug( $tax, $meta_value );
220
  if( $this->woocommerce_wpml->attributes->is_translatable_attribute( $tax ) && $attid ){
221
+
222
  $term_obj = $this->woocommerce_wpml->terms->wcml_get_term_by_id( $attid, $tax );
223
+ $trnsl_term_id = apply_filters( 'translate_object_id', $term_obj->term_id, $tax, false, $lang );
224
+
225
+ if( $trnsl_term_id ) {
226
+ $trnsl_term_obj = $this->woocommerce_wpml->terms->wcml_get_term_by_id( $trnsl_term_id, $tax );
227
+ $meta_value = $trnsl_term_obj->slug;
 
 
 
 
 
 
 
228
  }
229
  }
230
  }else{
248
  $meta_value = $values_arrs_tr[ $key ];
249
  }
250
  }
 
 
251
  }
252
  }
253
  $meta_key = 'attribute_'.$tax;
254
  }
 
255
  }
256
+ update_post_meta( $variation_id, $meta_key, $meta_value );
257
+ }elseif ( !isset( $settings[ $meta_key ] ) || $settings[ $meta_key ] == WPML_IGNORE_CUSTOM_FIELD ) {
258
+ continue;
259
  }
260
+
261
  //sync variation prices
262
  if(
263
  ( $this->woocommerce_wpml->settings[ 'enable_multi_currency' ] == WCML_MULTI_CURRENCIES_INDEPENDENT || $trbl ) &&
264
  in_array( $meta_key, array( '_sale_price', '_regular_price', '_price' ) )
265
  ){
266
+ $meta_value = get_post_meta( $original_variation_id, $meta_key, true );
267
+ update_post_meta( $variation_id, $meta_key, $meta_value );
268
  }
269
 
270
+ if( isset( $settings[ $meta_key ] ) && $settings[ $meta_key ] == WPML_TRANSLATE_CUSTOM_FIELD ){
271
  //sync custom fields
272
  $post_fields = $this->woocommerce_wpml->sync_product_data->sync_custom_field_value( $meta_key, $data, $variation_id, $post_fields, $original_variation_id, true );
273
  }
274
  }
275
  }
276
  }
277
+ }
278
+
279
+ public function delete_removed_variation_attributes( $orig_product_id, $variation_id ){
280
+
281
+ $original_product_attr = get_post_meta( $orig_product_id, '_product_attributes', true );
282
+
283
+ $get_all_variation_attributes = $this->wpdb->get_results(
284
+ $this->wpdb->prepare( "SELECT * FROM {$this->wpdb->postmeta} WHERE post_id = %d AND meta_key LIKE 'attribute_%%' ",
285
+ $variation_id )
286
+ );
287
+
288
+ foreach( $get_all_variation_attributes as $variation_attribute ){
289
+ $attribute_name = substr( $variation_attribute->meta_key, 10 );
290
+ if( !isset( $original_product_attr[ $attribute_name ] ) ){
291
+ delete_post_meta( $variation_id, $variation_attribute->meta_key );
292
+ }
293
+ }
294
+
295
+ }
296
+
297
+ public function get_product_variations( $product_id ){
298
+
299
+ $cache_key = $product_id;
300
+ $cache_group = 'product_variations';
301
+ $temp_product_variations = wp_cache_get( $cache_key, $cache_group );
302
+ if( $temp_product_variations ) return $temp_product_variations;
303
+
304
+ $variations = $this->wpdb->get_results(
305
+ $this->wpdb->prepare(
306
+ "SELECT * FROM {$this->wpdb->posts}
307
+ WHERE post_status IN ('publish','private')
308
+ AND post_type = 'product_variation'
309
+ AND post_parent = %d ORDER BY ID",
310
+ $product_id )
311
+ );
312
+
313
+ wp_cache_set( $cache_key, $variations, $cache_group );
314
+
315
+ return $variations;
316
  }
317
 
318
  public function remove_translations_for_variations(){
inc/wcml-cart-switch-lang-functions.php ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WCML_Cart_Switch_Lang_Functions{
4
+
5
+ private $lang_from;
6
+ private $lang_to;
7
+
8
+
9
+ function __construct(){
10
+
11
+ add_action( 'wp_footer', array( $this, 'wcml_language_switch_dialog' ) );
12
+ add_action( 'wp_loaded', array( $this, 'wcml_language_force_switch' ) );
13
+ add_action( 'wpml_user_switch_language', array( $this, 'language_has_switched' ), 10 , 2 );
14
+
15
+ }
16
+
17
+ public function language_has_switched( $lang_from, $lang_to ){
18
+
19
+ $settings = get_option( '_wcml_settings' );
20
+
21
+ if(
22
+ !isset( $_GET[ 'force_switch' ] ) &&
23
+ $lang_from != $lang_to &&
24
+ !empty( $settings ) &&
25
+ $settings[ 'cart_sync' ][ 'lang_switch' ] == WCML_CART_CLEAR
26
+ ){
27
+ $this->lang_from = $lang_from;
28
+ $this->lang_to = $lang_to;
29
+ }
30
+ }
31
+
32
+ function wcml_language_force_switch(){
33
+ global $woocommerce_wpml, $woocommerce;
34
+
35
+ if( isset( $_GET[ 'force_switch' ] ) && $_GET[ 'force_switch' ] == true ){
36
+ $woocommerce_wpml->cart->empty_cart_if_needed( 'lang_switch' );
37
+ $woocommerce->session->set( 'wcml_switched_type', 'lang_switch' );
38
+ }
39
+ }
40
+
41
+ function wcml_language_switch_dialog( ){
42
+ global $woocommerce_wpml, $sitepress;
43
+
44
+ $request_url = add_query_arg( 'force_switch', 0, $sitepress->convert_url( get_permalink(), $this->lang_from ) );
45
+
46
+ $cart_for_session = false;
47
+ if( isset( WC()->cart ) ){
48
+ $cart_for_session = WC()->cart->get_cart_for_session();
49
+ }
50
+
51
+ if( $this->lang_from && $this->lang_to && $request_url && !empty( $cart_for_session ) ) {
52
+
53
+ $force_cart_url = add_query_arg( 'force_switch', 1, get_permalink() );
54
+
55
+ $new_language_details = $sitepress->get_language_details( $this->lang_to );
56
+ $current_language_details = $sitepress->get_language_details( $this->lang_from );
57
+ $dialog_title = __( 'Switching language?', 'woocommerce-multilingual' );
58
+ $confirmation_message = sprintf( __( "You've switched language and there are items in the cart. If you keep the %s language, the cart will be emptied and you will have to add the items again to the cart.", 'woocommerce-multilingual' ), $new_language_details[ 'display_name' ] );
59
+ $stay_in = sprintf( __( 'Stay in %s', 'woocommerce-multilingual' ), $new_language_details[ 'display_name' ] );
60
+ $switch_to = sprintf( __( 'Switch back to %s', 'woocommerce-multilingual' ), $current_language_details[ 'display_name' ] );
61
+
62
+ $woocommerce_wpml->cart->cart_alert( $dialog_title, $confirmation_message, $stay_in, $switch_to, $force_cart_url, $request_url, true );
63
+ }
64
+ }
65
+
66
+ }
locale/woocommerce-multilingual-ar.mo CHANGED
Binary file
locale/woocommerce-multilingual-de_DE.mo CHANGED
Binary file
locale/woocommerce-multilingual-el.mo CHANGED
Binary file
locale/woocommerce-multilingual-es_ES.mo CHANGED
Binary file
locale/woocommerce-multilingual-fr_FR.mo CHANGED
Binary file
locale/woocommerce-multilingual-he_IL.mo CHANGED
Binary file
locale/woocommerce-multilingual-it_IT.mo CHANGED
Binary file
locale/woocommerce-multilingual-ja.mo CHANGED
Binary file
locale/woocommerce-multilingual-ko_KR.mo CHANGED
Binary file
locale/woocommerce-multilingual-nl_NL.mo CHANGED
Binary file
locale/woocommerce-multilingual-pl_PL.mo CHANGED
Binary file
locale/woocommerce-multilingual-pt_BR.mo CHANGED
Binary file
locale/woocommerce-multilingual-pt_PT.mo CHANGED
Binary file
locale/woocommerce-multilingual-ru_RU.mo CHANGED
Binary file
locale/woocommerce-multilingual-sv_SE.mo CHANGED
Binary file
locale/woocommerce-multilingual-uk_UA.mo CHANGED
Binary file
locale/woocommerce-multilingual-vi.mo CHANGED
Binary file
locale/woocommerce-multilingual-zh_CN.mo CHANGED
Binary file
locale/woocommerce-multilingual-zh_TW.mo CHANGED
Binary file
readme.txt CHANGED
@@ -5,7 +5,7 @@ Tags: CMS, woocommerce, commerce, ecommerce, e-commerce, products, WPML, multili
5
  License: GPLv2
6
  Requires at least: 3.9
7
  Tested up to: 4.7
8
- Stable tag: 3.9.5
9
 
10
  Allows running fully multilingual e-commerce sites using WooCommerce and WPML.
11
 
@@ -142,6 +142,18 @@ WooCommerce Multilingual is compatible with all major WooCommerce extensions. We
142
 
143
  == Changelog ==
144
 
 
 
 
 
 
 
 
 
 
 
 
 
145
  = 3.9.5 =
146
  * Fixed a bug introduced in 3.9.4 that prevented translating variable products
147
 
5
  License: GPLv2
6
  Requires at least: 3.9
7
  Tested up to: 4.7
8
+ Stable tag: 4.0.0
9
 
10
  Allows running fully multilingual e-commerce sites using WooCommerce and WPML.
11
 
142
 
143
  == Changelog ==
144
 
145
+ = 4.0.0 =
146
+ * Added the option to configure automatic exchange rates for the multi-currency mode
147
+ * Optimized the synchronization process between products and their translations when saving products
148
+ * Added the option to reset the cart when switching the languages or currencies
149
+ * Added compatibility updates for WordPress 4.7
150
+ * Improved usability aspects related to popular compatible extensions
151
+ * Added compatibility updates for upcoming WooCommerce 2.7
152
+ * Fixed a compatibility issue with Yoast SEO premium: Redirects to the original product were created for translated variations
153
+ * Fixed a compatibility issue with WooCommerce Tab Manager: HTML was stripped out when saving the translation of a tab
154
+ * Bug fix: downloadable products were added multiple times to the cart (instead of quantity change)
155
+ * Bug fix: order-pay endpoint string was re-registering itself with a blank value
156
+
157
  = 3.9.5 =
158
  * Fixed a bug introduced in 3.9.4 that prevented translating variable products
159
 
res/css/admin.css CHANGED
@@ -1 +1,64 @@
1
- .wcml-menu-warn{display:inline-block;color:#d54e21;line-height:15px;margin:1px 0 0 2px;z-index:26}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .wcml-menu-warn {
2
+ display: inline-block;
3
+ color: #d54e21;
4
+ line-height: 15px;
5
+ margin: 1px 0 0 2px;
6
+ z-index: 26;
7
+ }
8
+
9
+ a.wcml-external-link {
10
+ padding-right: 15px;
11
+ }
12
+
13
+ a.wcml-external-link:after {
14
+ content: "\f504";
15
+ display: inline-block;
16
+ width: 15px;
17
+ margin-right: -15px;
18
+ font-size: 14px;
19
+ line-height: 18px;
20
+ font-family: dashicons;
21
+ text-decoration: none;
22
+ font-weight: normal;
23
+ font-style: normal;
24
+ vertical-align: top;
25
+ -webkit-font-smoothing: antialiased;
26
+ -moz-osx-font-smoothing: grayscale;
27
+ }
28
+
29
+ .wcml-pointer-inner .wcml-information-paragraph {
30
+ padding-right: 30px;
31
+ }
32
+
33
+ .wcml-pointer-inner .wp-pointer-buttons {
34
+ padding: 0;
35
+ }
36
+
37
+ .wcml-pointer-inner.wp-pointer-bottom .wp-pointer-arrow {
38
+ left: auto;
39
+ right: 50px;
40
+ }
41
+
42
+ .wcml-message-icon.wcml-table-cell,
43
+ .wcml-message-content.wcml-table-cell {
44
+ height: 100px;
45
+ }
46
+
47
+ .wcml-pointer-link {
48
+ position: relative;
49
+ text-decoration: none;
50
+ padding: 10px;
51
+ }
52
+
53
+ .wcml-cart-dialog button {
54
+ text-transform: capitalize;
55
+ }
56
+
57
+ div[data-selector="woocommerce_table_rate_title"] a,
58
+ div[data-selector="wpbody-content .woocommerce h2"] a {
59
+ padding: 10px 0 0 0;
60
+ }
61
+
62
+ #shipping_rates .shipping_label .wcml-pointer-link {
63
+ padding: 0;
64
+ }
res/css/currency-switcher.css CHANGED
@@ -1 +1 @@
1
- .wcml-active-currency{background-color:#E5E5E5}ul.wcml_currency_switcher{padding:0 !important;margin:0 !important;list-style-type:none !important;position:relative}ul.wcml_currency_switcher li{cursor:pointer;border:1px solid #cdcdcd}ul.wcml_currency_switcher.curr_list_vertical{border-top:1px solid #cdcdcd;display:inline-block}ul.wcml_currency_switcher.curr_list_horizontal li{float:left;position:relative;padding:2px 5px;margin-left:1px}ul.wcml_currency_switcher.curr_list_horizontal li:first-child{margin-left:0}ul.wcml_currency_switcher.curr_list_vertical li{border-top-width:0;cursor:pointer;padding:3px 10px;margin:0}
1
+ .wcml-active-currency{background-color:#E5E5E5}ul.wcml_currency_switcher{padding:0 !important;margin:0 !important;list-style-type:none !important;position:relative}ul.wcml_currency_switcher li{cursor:pointer;border:1px solid #cdcdcd}ul.wcml_currency_switcher.curr_list_vertical{border-top:1px solid #cdcdcd;display:inline-block}ul.wcml_currency_switcher.curr_list_horizontal li{float:left;position:relative;padding:2px 5px;margin-left:1px}ul.wcml_currency_switcher.curr_list_horizontal li:first-child{margin-left:0}ul.wcml_currency_switcher.curr_list_vertical li{border-top-width:0;cursor:pointer;padding:3px 10px;margin:0}.exchange-rates-online-wrap,.service-details-wrap{padding-left:24px}.rtl .service-details-wrap,.rtl .exchange-rate-api-key-wrap{padding-left:0;padding-right:24px}.exchange-rate-service-website{text-decoration:none}.exchange-rate-service-website .dashicons-external{font-size:14px;width:14px;height:14px;vertical-align:-4px}
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}.wcml-wrap{margin-bottom:20px;min-width:900px}.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{min-width:930px}.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;min-width:900px;overflow:hidden}.wcml-section:last-of-type{border:none;margin:0}.wcml-section-content .wcml-section-content-inner{margin:0 0 20px 0;padding:0 0 10px 0;border-bottom:1px solid #ededed;float:left;width:100%}.wcml-section-header{width:300px;float:left}.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}.wcml-section-content{float:left;width:570px;margin-left:30px}.wcml-section-content-wide{width:-webkit-calc(100% - 360px);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{width:215px;text-align:left}.wcml-co-dialog input,.wcml-co-dialog select{width:145px}.wcml-co-dialog .currency_code label{width:100px;vertical-align:top}.wcml-co-dialog .currency_code select{width:auto;max-width:-webkit-calc(100% - 165px);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:70px}.wcml-co-dialog .wcml-co-exchange-rate .wcml-co-set-rate{display:inline-block;padding:4px 15px 7px 15px}.wcml-co-dialog .wcml-co-exchange-rate small{display:block}.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}table.widefat.currency_table{float:left;width:300px;border-right:none}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:145px;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}table.widefat.currency_table td.wcml-col-rate .truncate{max-width:75px;display:block}table.widefat.currency_delete_table{float:left;width:50px;border-left:none;clear:none}table.widefat.currency_delete_table td.wcml-col-delete{vertical-align:middle;text-align:center}table.widefat.currency_delete_table td.wcml-col-delete: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:-webkit-linear-gradient(top, #2a95c5, #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}table.widefat.currency_lang_table{border-left:none;border-right:none}table.widefat.currency_lang_table thead tr{height:28px}table.widefat.currency_lang_table thead td{border-bottom:0;text-align:center;padding-top:3px;padding-bottom:1px;font-size:1em}table.widefat.currency_lang_table thead th{padding-top:0;padding-bottom:0;text-align:center}.currency_wrap{width:-webkit-calc(100% - 300px - 50px);width:calc(100% - 300px - 50px);float:left;margin-bottom:10px}.currency_inner{overflow-x:auto;overflow-y:visible}.currency_table,.currency_lang_table,.currency_delete_table{clear:none}.currency_table thead tr,.currency_lang_table thead tr,.currency_delete_table thead tr{height:56px}.currency_table tr,.currency_lang_table tr,.currency_delete_table tr{height:50px}.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}.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:0 8px 0 0;padding:2px 8px;border:1px solid #DFDFDF;border-radius:2px;background:-webkit-linear-gradient(bottom, #ECECEC, #F9F9F9) repeat scroll 0 0 #F1F1F1;background:linear-gradient(to top, #ECECEC, #F9F9F9) repeat scroll 0 0 #F1F1F1;cursor:move}.wcml_currencies_order_ajx_resp{padding-top:5px;color:#E68A00}.explanation-text{color:#999}input[name="wcml_curr_template"]{width:100%}.wcml_curr_style label{line-height:30px}.wcml-currency-preview{margin:15px 0 30px;display:inline-block}.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-plugins-status-list li,.wcml-status-list.wcml-tax-translation-list li{margin-bottom:15px}.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}.wcml-wrap{margin-bottom:20px;min-width:900px}.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{min-width:930px}.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;min-width:900px;overflow:hidden}.wcml-section:last-of-type{border:none;margin:0}.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{width:310px;float:left}.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}.wcml-section-content{float:left;width:680px;margin-left:30px}.wcml-section-content-wide{width:-webkit-calc(100% - 360px);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{width:215px;text-align:left}.wcml-co-dialog input,.wcml-co-dialog select{width:145px}.wcml-co-dialog .currency_code label{width:100px;vertical-align:top}.wcml-co-dialog .currency_code select{width:auto;max-width:-webkit-calc(100% - 165px);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}table.widefat.currency_table{float:left;width:320px;border-right:none}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:120px;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}table.widefat.currency_table td.wcml-col-rate .truncate{max-width:75px;display:block}table.widefat.currency_delete_table{float:left;width:50px;border-left:none;clear:none}table.widefat.currency_delete_table td.wcml-col-delete{vertical-align:middle;text-align:center}table.widefat.currency_delete_table td.wcml-col-delete: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:-webkit-linear-gradient(top, #2a95c5, #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}table.widefat.currency_lang_table{border-left:none;border-right:none}table.widefat.currency_lang_table thead tr{height:28px}table.widefat.currency_lang_table thead td{border-bottom:0;text-align:center;padding-top:3px;padding-bottom:1px;font-size:1em}table.widefat.currency_lang_table thead th{padding-top:0;padding-bottom:0;text-align:center}.currency_wrap{width:-webkit-calc(100% - 320px - 50px);width:calc(100% - 320px - 50px);float:left;margin-bottom:10px}.currency_inner{overflow-x:auto;overflow-y:visible}.currency_table,.currency_lang_table,.currency_delete_table{clear:none}.currency_table thead tr,.currency_lang_table thead tr,.currency_delete_table thead tr{height:56px}.currency_table tr,.currency_lang_table tr,.currency_delete_table tr{height:50px}.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}.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:-webkit-linear-gradient(bottom, #ECECEC, #F9F9F9) repeat scroll 0 0 #F1F1F1;background:linear-gradient(to top, #ECECEC, #F9F9F9) repeat scroll 0 0 #F1F1F1;cursor:move}.wcml_currencies_order_ajx_resp{padding-top:5px;color:#E68A00}.explanation-text{color:#999}input[name="wcml_curr_template"]{width:100%}.wcml_curr_style label{line-height:30px}.wcml-currency-preview{margin:15px 0 30px;display:inline-block}.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/cart_widget.min.js CHANGED
@@ -1 +1 @@
1
- jQuery(document).ready(function(a){try{wc_cart_fragments_params.ajax_url.toString()+"-wc_cart_hash";""!=sessionStorage.getItem("woocommerce_cart_hash")&&1!=actions.is_lang_switched&&1!=actions.is_currency_switched||sessionStorage.removeItem("wc_fragments")}catch(a){}});
1
+ jQuery(document).ready(function(a){try{wc_cart_fragments_params.ajax_url.toString()+"-wc_cart_hash";(""==sessionStorage.getItem("woocommerce_cart_hash")||1==actions.is_lang_switched||1==actions.is_currency_switched)&&sessionStorage.removeItem("wc_fragments")}catch(b){}});
res/js/dialogs.min.js CHANGED
@@ -1 +1 @@
1
- var WCML_Dialog=WCML_Dialog||{};jQuery(function(a){WCML_Dialog.dialog=function(b,c){var d=this;"undefined"==typeof b&&(b="generic"),d.overflow_y=a("body").css("overflow-y"),a("body").css("overflow-y","hidden");var e=a("#wcml-dialog-"+b),f=a("#"+b).attr("title");if("undefined"==typeof f&&(f="undefined"!=c.title?c.title:""),!e.length){a(document.body).append(a('<div class="wcml-dialog-container" title="'+f+'" id="wcml-dialog-'+b+'" />')),e=a("#wcml-dialog-"+b);var g=a(window).height(),h={title:"",autoOpen:!1,show:!0,dialogClass:"wcml-ui-dialog otgs-ui-dialog",position:{my:"center",at:"center",of:window},modal:!0,width:"90%",height:.7*g,resizable:!1,draggable:!1,beforeOpen:function(a){},beforeClose:function(a){},close:function(b){a("body").css("overflow-y",d.overflow_y)},create:function(a){},focus:function(a){},open:function(a){},refresh:function(a){}};"undefined"!=typeof c.height&&(h.height=Math.min(.7*g,c.height)),"undefined"!=typeof c.width&&(h.width=c.width),WCML_Dialog.using_wpdialog?e.wpdialog(h):e.dialog(h)}if(WCML_Dialog.using_wpdialog?e.wpdialog("open"):e.dialog("open"),c.action){var i=a('<div class="spinner"></div>');i.css({display:"inline-block",visibility:"visible",float:"none"}),e.html(i),a.ajax({url:ajaxurl,type:"post",dataType:"json",data:c,success:function(a){e.html(a.html)}})}return c.content&&a("#"+c.content).length&&e.html(a("#"+c.content).html()),"undefined"!=typeof WCML_Tooltip&&WCML_Tooltip.init(),!1},WCML_Dialog._register_open_handler=function(){a(document).on("click",".js-wcml-dialog-trigger",function(b){b.preventDefault();var c=!1;a(this).data("dialog")?c=a(this).data("dialog"):a(this).data("action")&&(c=a(this).data("action")),c&&(a(this).data("action")&&a(this).data("action",a(this).data("action").replace(/-/g,"_")),WCML_Dialog.dialog(c,a(this).data()))})},WCML_Dialog._register_close_handler=function(){a(document).on("click",".wcml-dialog-close-button",function(b){b.preventDefault(),"undefined"!=typeof tinyMCE&&tinyMCE.triggerSave(),a(".wcml-dialog").find(".mce_editor textarea").each(function(){var b=a(this).attr("id"),c=a(this);if(b in tinyMCE.editors){var d=tinyMCE.get(b);d.isHidden()||c.val(d.getContent())}});var c=a(this).closest(".wcml-dialog-container"),d=a(this);d.attr("disabled","disabled");var e=a(this).data();if(e.action){var f=a('<div class="spinner"></div>');f.css({visibility:"visible",float:"right"}).prependTo(a(".wcml-dialog-footer .alignright")),a.ajax({url:ajaxurl,type:"post",dataType:"json",data:{action:e.action,fields:d.closest(".wcml-dialog-container").find("form").serialize(),icl_nonce:e.nonce},async:!1,success:function(a){e.stay&&(f.remove(),d.removeAttr("disabled"))}})}e.stay||(d.trigger("before_close_dialog"),WCML_Dialog.using_wpdialog?c.wpdialog("close"):c.dialog("close"))})},WCML_Dialog.init=function(){a(document).ready(function(){"undefined"!=typeof a.wp?WCML_Dialog.using_wpdialog="undefined"!=typeof a.wp.wpdialog:WCML_Dialog.using_wpdialog=!1,WCML_Dialog._register_open_handler(),WCML_Dialog._register_close_handler()})},WCML_Dialog.init()});
1
+ var WCML_Dialog=WCML_Dialog||{};jQuery(function(a){WCML_Dialog.dialog=function(b,c){var d=this;"undefined"==typeof b&&(b="generic"),d.overflow_y=a("body").css("overflow-y"),a("body").css("overflow-y","hidden");var e=a("#wcml-dialog-"+b),f=a("#"+b).attr("title");if("undefined"==typeof f&&(f="undefined"!=c.title?c.title:""),!e.length){a(document.body).append(a('<div class="wcml-dialog-container" title="'+f+'" id="wcml-dialog-'+b+'" />')),e=a("#wcml-dialog-"+b);var g=a(window).height(),h={title:"",autoOpen:!1,show:!0,dialogClass:"wcml-ui-dialog otgs-ui-dialog",position:{my:"center",at:"center",of:window},modal:!0,width:"90%",height:.7*g,resizable:!1,draggable:!1,beforeOpen:function(a){},beforeClose:function(a){},close:function(b){a("body").css("overflow-y",d.overflow_y)},create:function(a){},focus:function(a){},open:function(a){},refresh:function(a){}};"undefined"!=typeof c.height&&(h.height=Math.min(.7*g,c.height)),"undefined"!=typeof c.width&&(h.width=c.width),WCML_Dialog.using_wpdialog?e.wpdialog(h):e.dialog(h)}if(WCML_Dialog.using_wpdialog?e.wpdialog("open"):e.dialog("open"),c.action){var i=a('<div class="spinner"></div>');i.css({display:"inline-block",visibility:"visible","float":"none"}),e.html(i),a.ajax({url:ajaxurl,type:"post",dataType:"json",data:c,success:function(a){e.html(a.html)}})}return c.content&&a("#"+c.content).length&&e.html(a("#"+c.content).html()),"undefined"!=typeof WCML_Tooltip&&WCML_Tooltip.init(),!1},WCML_Dialog._register_open_handler=function(){a(document).on("click",".js-wcml-dialog-trigger",function(b){b.preventDefault();var c=!1;a(this).data("dialog")?c=a(this).data("dialog"):a(this).data("action")&&(c=a(this).data("action")),c&&(a(this).data("action")&&a(this).data("action",a(this).data("action").replace(/-/g,"_")),WCML_Dialog.dialog(c,a(this).data()))})},WCML_Dialog._register_close_handler=function(){a(document).on("click",".wcml-dialog-close-button",function(b){b.preventDefault(),"undefined"!=typeof tinyMCE&&tinyMCE.triggerSave(),a(".wcml-dialog").find(".mce_editor textarea").each(function(){var b=a(this).attr("id"),c=a(this);if(b in tinyMCE.editors){var d=tinyMCE.get(b);d.isHidden()||c.val(d.getContent())}});var c=a(this).closest(".wcml-dialog-container"),d=a(this);d.attr("disabled","disabled");var e=a(this).data();if(e.action){var f=a('<div class="spinner"></div>');f.css({visibility:"visible","float":"right"}).prependTo(a(".wcml-dialog-footer .alignright")),a.ajax({url:ajaxurl,type:"post",dataType:"json",data:{action:e.action,fields:d.closest(".wcml-dialog-container").find("form").serialize(),icl_nonce:e.nonce},async:!1,success:function(a){e.stay&&(f.remove(),d.removeAttr("disabled"))}})}e.stay||(d.trigger("before_close_dialog"),WCML_Dialog.using_wpdialog?c.wpdialog("close"):c.dialog("close"))})},WCML_Dialog.init=function(){a(document).ready(function(){"undefined"!=typeof a.wp?WCML_Dialog.using_wpdialog="undefined"!=typeof a.wp.wpdialog:WCML_Dialog.using_wpdialog=!1,WCML_Dialog._register_open_handler(),WCML_Dialog._register_close_handler()})},WCML_Dialog.init()});
res/js/exchange-rates.js ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery( function($){
2
+
3
+ WCMLExchangeRates = {
4
+
5
+ init: function(){
6
+
7
+ $('#online-exchange-rates').on( 'change', '#exchange-rates-automatic', WCMLExchangeRates.toggleManualAutomatic );
8
+ $('#online-exchange-rates').on( 'click', '#update-rates-manually', WCMLExchangeRates.updateRatesManually);
9
+ $('#online-exchange-rates').on( 'change', 'input[name=exchange-rates-service]', WCMLExchangeRates.selectService );
10
+ $('#online-exchange-rates').on( 'change', 'input[name=update-schedule]', WCMLExchangeRates.updateFrequency );
11
+
12
+ WCMLExchangeRates.selectedService = $('input[name=exchange-rates-service]:checked').val();
13
+ $('#online-exchange-rates').on( 'change', 'input[name=exchange-rates-service]', WCMLExchangeRates.toggleUpdateManuallyButton );
14
+ $('#online-exchange-rates').on( 'change', 'input[name=lifting_charge]', WCMLExchangeRates.toggleUpdateManuallyButton );
15
+
16
+ },
17
+
18
+ toggleManualAutomatic: function(){
19
+
20
+ if($(this).attr('checked') == 'checked'){
21
+ $('#exchange-rates-online-wrap').fadeIn();
22
+ }else{
23
+ $('#exchange-rates-online-wrap').fadeOut();
24
+ }
25
+
26
+ },
27
+
28
+ updateRatesManually: function(){
29
+
30
+ var updateButton = $(this);
31
+
32
+ $('#exchange-rates-error').html('').hide();
33
+ $('#update-rates-spinner').css({ visibility: 'visible' });
34
+ $('.exchange-rates-sources .notice-error').html('').hide();
35
+ updateButton.attr('disabled', 'disabled');
36
+
37
+ $.ajax({
38
+ type: "post",
39
+ url: ajaxurl,
40
+ dataType: 'json',
41
+ data: {
42
+ action: "wcml_update_exchange_rates",
43
+ wcml_nonce: $('#update-exchange-rates-nonce').val()
44
+ },
45
+ success: function (response) {
46
+
47
+ if (response.success) {
48
+ $('#exchange-rates-success').fadeIn();
49
+ $('#update-rates-time .time').html( response.last_updated );
50
+ }else{
51
+ if( response.error ){
52
+ var serviceErrorWrap = $('#service-error-' + response.service );
53
+ serviceErrorWrap.html( response.error ).fadeIn();
54
+ }
55
+ }
56
+
57
+ $('#update-rates-spinner').css({ visibility: 'hidden' });
58
+ updateButton.removeAttr('disabled');
59
+
60
+ for( code in response.rates ){
61
+ $('#currency_row_' + code + ' span.rate').hide().html( response.rates[code] ).fadeIn('slow');
62
+ }
63
+
64
+ }
65
+ })
66
+
67
+ },
68
+
69
+ /**
70
+ * @todo remove when moving to auto-saving forms
71
+ */
72
+ toggleUpdateManuallyButton: function(){
73
+
74
+ if( WCMLExchangeRates.selectedService == $(this).val() ){
75
+ $('#update-rates-manually').removeAttr( 'disabled' ).next('.wcml-tip').hide();
76
+ } else {
77
+ $('#update-rates-manually').attr( 'disabled', 'disabled' ).next('.wcml-tip').show().tipTip( WCML_Tooltip.default_args);
78
+ }
79
+
80
+ },
81
+
82
+ selectService: function(){
83
+
84
+ $('.service-details-wrap').hide();
85
+ $(this).parent().find('.service-details-wrap').show();
86
+
87
+ },
88
+
89
+ updateFrequency: function(){
90
+
91
+ $('[name="update-weekly-day"], [name="update-monthly-day"]').attr('disabled', 'disabled');
92
+ $(this).parent().find('select').removeAttr('disabled');
93
+
94
+ }
95
+ }
96
+
97
+
98
+
99
+ WCMLExchangeRates.init();
100
+
101
+ });
res/js/front-scripts.js ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(document).ready(function ($) {
2
+
3
+ jQuery(document).on( 'click', '.wcml_removed_cart_items_clear', function(e){
4
+ e.preventDefault();
5
+
6
+ jQuery.ajax({
7
+ type : 'post',
8
+ url : woocommerce_params.ajax_url,
9
+ data : {
10
+ action: 'wcml_cart_clear_removed_items',
11
+ wcml_nonce: jQuery('#wcml_clear_removed_items_nonce').val()
12
+ },
13
+ success: function(response) {
14
+ window.location = window.location.href;
15
+ }
16
+ });
17
+ });
18
+
19
+ });
20
+
res/js/front-scripts.min.js ADDED
@@ -0,0 +1 @@
 
1
+ jQuery(document).ready(function(a){jQuery(document).on("click",".wcml_removed_cart_items_clear",function(a){a.preventDefault(),jQuery.ajax({type:"post",url:woocommerce_params.ajax_url,data:{action:"wcml_cart_clear_removed_items",wcml_nonce:jQuery("#wcml_clear_removed_items_nonce").val()},success:function(a){window.location=window.location.href}})})});
res/js/jquery.cookie.min.js CHANGED
@@ -1 +1 @@
1
- !function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a(jQuery)}(function(a){function b(a){return a}function c(a){return decodeURIComponent(a.replace(e," "))}function d(a){0===a.indexOf('"')&&(a=a.slice(1,-1).replace(/\\"/g,'"').replace(/\\\\/g,"\\"));try{return f.json?JSON.parse(a):a}catch(a){}}var e=/\+/g,f=a.cookie=function(e,g,h){if(void 0!==g){if(h=a.extend({},f.defaults,h),"number"==typeof h.expires){var i=h.expires,j=h.expires=new Date;j.setDate(j.getDate()+i)}return g=f.json?JSON.stringify(g):String(g),document.cookie=[f.raw?e:encodeURIComponent(e),"=",f.raw?g:encodeURIComponent(g),h.expires?"; expires="+h.expires.toUTCString():"",h.path?"; path="+h.path:"",h.domain?"; domain="+h.domain:"",h.secure?"; secure":""].join("")}for(var k=f.raw?b:c,l=document.cookie.split("; "),m=e?void 0:{},n=0,o=l.length;n<o;n++){var p=l[n].split("="),q=k(p.shift()),r=k(p.join("="));if(e&&e===q){m=d(r);break}e||(m[q]=d(r))}return m};f.defaults={},a.removeCookie=function(b,c){return void 0!==a.cookie(b)&&(a.cookie(b,"",a.extend({},c,{expires:-1})),!0)}});
1
+ !function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a(jQuery)}(function(a){function b(a){return a}function c(a){return decodeURIComponent(a.replace(e," "))}function d(a){0===a.indexOf('"')&&(a=a.slice(1,-1).replace(/\\"/g,'"').replace(/\\\\/g,"\\"));try{return f.json?JSON.parse(a):a}catch(b){}}var e=/\+/g,f=a.cookie=function(e,g,h){if(void 0!==g){if(h=a.extend({},f.defaults,h),"number"==typeof h.expires){var i=h.expires,j=h.expires=new Date;j.setDate(j.getDate()+i)}return g=f.json?JSON.stringify(g):String(g),document.cookie=[f.raw?e:encodeURIComponent(e),"=",f.raw?g:encodeURIComponent(g),h.expires?"; expires="+h.expires.toUTCString():"",h.path?"; path="+h.path:"",h.domain?"; domain="+h.domain:"",h.secure?"; secure":""].join("")}for(var k=f.raw?b:c,l=document.cookie.split("; "),m=e?void 0:{},n=0,o=l.length;o>n;n++){var p=l[n].split("="),q=k(p.shift()),r=k(p.join("="));if(e&&e===q){m=d(r);break}e||(m[q]=d(r))}return m};f.defaults={},a.removeCookie=function(b,c){return void 0!==a.cookie(b)?(a.cookie(b,"",a.extend({},c,{expires:-1})),!0):!1}});
res/js/languages_notice.min.js CHANGED
@@ -1 +1 @@
1
- jQuery(document).ready(function(){jQuery(document).on("click","#wcml_translations_message",function(a){a.preventDefault(),jQuery.ajax({type:"post",url:ajaxurl,data:{action:"hide_wcml_translations_message",wcml_nonce:jQuery("#wcml_hide_languages_notice").val()},success:function(a){jQuery("#wcml_translations_message").remove()}})}),jQuery(document).on("click","#icl_save_language_selection",function(){jQuery("#icl_avail_languages_picker li input").each(function(){if(jQuery(this).is(":checked")&&0===jQuery("#default_language_"+jQuery(this).val()).length)return jQuery('<p class="icl_ajx_response" style="display: block">'+wcml_settings.warn+"</p>").insertBefore("#icl_ajx_response"),!1})})});
1
+ jQuery(document).ready(function(){jQuery(document).on("click","#wcml_translations_message",function(a){a.preventDefault(),jQuery.ajax({type:"post",url:ajaxurl,data:{action:"hide_wcml_translations_message",wcml_nonce:jQuery("#wcml_hide_languages_notice").val()},success:function(a){jQuery("#wcml_translations_message").remove()}})}),jQuery(document).on("click","#icl_save_language_selection",function(){jQuery("#icl_avail_languages_picker li input").each(function(){return jQuery(this).is(":checked")&&0===jQuery("#default_language_"+jQuery(this).val()).length?(jQuery('<p class="icl_ajx_response" style="display: block">'+wcml_settings.warn+"</p>").insertBefore("#icl_ajx_response"),!1):void 0})})});
res/js/lock_fields.min.js CHANGED
@@ -1 +1 @@
1
- jQuery(document).ready(function(a){var b,c=["_virtual","_downloadable","product-type","_backorders","_manage_stock","_stock","_stock_status","_sold_individually","comment_status","_tax_status","_tax_class","parent_id","crosssell_ids","upsell_ids"];for(1==unlock_fields.file_paths&&c.push("_download_type"),c=c.concat(non_standard_fields.ids),a(".wcml_prod_hidden_notice").prependTo("#woocommerce-product-data"),b=0;b<c.length;b++)a("#"+c[b]).attr("disabled","disabled"),a("#"+c[b]).after(a(".wcml_lock_img").clone().removeClass("wcml_lock_img").show());var d=["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"];for(d=d.concat(non_standard_fields.classes),1==unlock_fields.file_paths&&(d.push("upload_file_button"),d.push("insert"),d.push("delete"),a(".upload_file_button,.insert,.delete").bind({click:function(a){return!1}})),b=0;b<d.length;b++)a("."+d[b]).attr("disabled","disabled"),a("."+d[b]).after(a(".wcml_lock_img").clone().removeClass("wcml_lock_img").show());a("#visibility .edit-visibility span").bind({click:function(a){return!1}}),a(".remove_variation").each(function(){a(this).attr("disabled","disabled"),a(this).after(a(".wcml_lock_img").clone().removeClass("wcml_lock_img").show().css("float","right"))});var e=["_width","_height","_sku","_length","_weight","product_length","_regular_price","_sale_price","_sale_price_dates_from","_sale_price_dates_to"];for(1==unlock_fields.file_paths&&(e.push("_download_limit"),e.push("_download_expiry"),e.push("_wc_file_names[]"),e.push("_wc_file_urls[]")),e=e.concat(non_standard_fields.input_names),1==unlock_fields.menu_order&&e.push("menu_order"),b=0;b<e.length;b++)a('input[name="'+e[b]+'"]').attr("readonly","readonly"),a(".dimensions_field span.wrap").css("float","left"),"_width"!=e[b]&&"_height"!=e[b]&&"_length"!=e[b]||(a('input[name="'+e[b]+'"]').css("margin-right",0),a('input[name="'+e[b]+'"]').css("float","none"),a('input[name="'+e[b]+'"]').css("width","29%")),"_sale_price_dates_to"==e[b]?a('input[name="'+e[b]+'"]').after(a(".wcml_lock_img").clone().removeClass("wcml_lock_img").css("float","left").show()):a('input[name="'+e[b]+'"]').after(a(".wcml_lock_img").clone().removeClass("wcml_lock_img").show());a('#product_attributes td textarea,#product_attributes input[type="text"]').each(function(){a(this).attr("readonly","readonly"),a(this).after(a(".wcml_lock_img").clone().removeClass("wcml_lock_img").show())}),a('#product_attributes input[type="checkbox"]').each(function(){a(this).attr("disabled","disabled"),a(this).after(a(".wcml_lock_img").clone().removeClass("wcml_lock_img").show())}),a('form#post input[type="submit"]').click(function(){for(b=0;b<c.length;b++)a("#"+c[b]).removeAttr("disabled");a('.woocommerce_variation select,#variable_product_options .toolbar select,.woocommerce_variation input[type="checkbox"],#product_attributes input[type="checkbox"]').each(function(){a(this).removeAttr("disabled")})})});var wcml_lock_variation_fields=function(){var a=jQuery(".woocommerce_variation>h3 select").attr("disabled");if("undefined"==typeof a||a===!1){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 b=0,c=["_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(b=0;b<c.length;b++)jQuery('input[name^="variable'+c[b]+'"]').each(function(){jQuery(this).attr("readonly","readonly"),jQuery(this).after(jQuery(".wcml_lock_img").clone().removeClass("wcml_lock_img").show())});var d=["_enabled","_is_downloadable","_is_virtual","_manage_stock"];for(b=0;b<d.length;b++)jQuery('input[name^="variable'+d[b]+'"]').each(function(){jQuery(this).attr("disabled","disabled"),jQuery(this).after(jQuery(".wcml_lock_img").clone().removeClass("wcml_lock_img").show())});var e=["_stock_status","_shipping_class","_tax_class"];for(b=0;b<e.length;b++)jQuery('select[name^="variable'+e[b]+'"]').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(1==unlock_fields.file_paths){var f=["_wc_variation_file_names","_wc_variation_file_urls"];for(b=0;b<f.length;b++)jQuery('input[name^="'+f[b]+'"]').each(function(){jQuery(this).attr("readonly","readonly"),jQuery(this).after(jQuery(".wcml_lock_img").clone().removeClass("wcml_lock_img").show())});var g=["upload_file_button","insert","delete"];for(b=0;b<g.length;b++)jQuery("."+g[b]).attr("disabled","disabled"),jQuery("."+g[b]).after(jQuery(".wcml_lock_img").clone().removeClass("wcml_lock_img").show().css("float","right"))}}};
1
+ jQuery(document).ready(function(a){var b,c=["_virtual","_downloadable","product-type","_backorders","_manage_stock","_stock","_stock_status","_sold_individually","comment_status","_tax_status","_tax_class","parent_id","crosssell_ids","upsell_ids"];for(1==unlock_fields.file_paths&&c.push("_download_type"),c=c.concat(non_standard_fields.ids),a(".wcml_prod_hidden_notice").prependTo("#woocommerce-product-data"),b=0;b<c.length;b++)a("#"+c[b]).attr("disabled","disabled"),a("#"+c[b]).after(a(".wcml_lock_img").clone().removeClass("wcml_lock_img").show());var d=["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"];for(d=d.concat(non_standard_fields.classes),1==unlock_fields.file_paths&&(d.push("upload_file_button"),d.push("insert"),d.push("delete"),a(".upload_file_button,.insert,.delete").bind({click:function(a){return!1}})),b=0;b<d.length;b++)a("."+d[b]).attr("disabled","disabled"),a("."+d[b]).after(a(".wcml_lock_img").clone().removeClass("wcml_lock_img").show());a("#visibility .edit-visibility span").bind({click:function(a){return!1}}),a(".remove_variation").each(function(){a(this).attr("disabled","disabled"),a(this).after(a(".wcml_lock_img").clone().removeClass("wcml_lock_img").show().css("float","right"))});var e=["_width","_height","_sku","_length","_weight","product_length","_regular_price","_sale_price","_sale_price_dates_from","_sale_price_dates_to"];for(1==unlock_fields.file_paths&&(e.push("_download_limit"),e.push("_download_expiry"),e.push("_wc_file_names[]"),e.push("_wc_file_urls[]")),e=e.concat(non_standard_fields.input_names),1==unlock_fields.menu_order&&e.push("menu_order"),b=0;b<e.length;b++)a('input[name="'+e[b]+'"]').attr("readonly","readonly"),a(".dimensions_field span.wrap").css("float","left"),("_width"==e[b]||"_height"==e[b]||"_length"==e[b])&&(a('input[name="'+e[b]+'"]').css("margin-right",0),a('input[name="'+e[b]+'"]').css("float","none"),a('input[name="'+e[b]+'"]').css("width","29%")),"_sale_price_dates_to"==e[b]?a('input[name="'+e[b]+'"]').after(a(".wcml_lock_img").clone().removeClass("wcml_lock_img").css("float","left").show()):a('input[name="'+e[b]+'"]').after(a(".wcml_lock_img").clone().removeClass("wcml_lock_img").show());a('#product_attributes td textarea,#product_attributes input[type="text"]').each(function(){a(this).attr("readonly","readonly"),a(this).after(a(".wcml_lock_img").clone().removeClass("wcml_lock_img").show())}),a('#product_attributes input[type="checkbox"]').each(function(){a(this).attr("disabled","disabled"),a(this).after(a(".wcml_lock_img").clone().removeClass("wcml_lock_img").show())}),a('form#post input[type="submit"]').click(function(){for(b=0;b<c.length;b++)a("#"+c[b]).removeAttr("disabled");a('.woocommerce_variation select,#variable_product_options .toolbar select,.woocommerce_variation input[type="checkbox"],#product_attributes input[type="checkbox"]').each(function(){a(this).removeAttr("disabled")})})});var wcml_lock_variation_fields=function(){var a=jQuery(".woocommerce_variation>h3 select").attr("disabled");if("undefined"==typeof a||a===!1){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 b=0,c=["_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(b=0;b<c.length;b++)jQuery('input[name^="variable'+c[b]+'"]').each(function(){jQuery(this).attr("readonly","readonly"),jQuery(this).after(jQuery(".wcml_lock_img").clone().removeClass("wcml_lock_img").show())});var d=["_enabled","_is_downloadable","_is_virtual","_manage_stock"];for(b=0;b<d.length;b++)jQuery('input[name^="variable'+d[b]+'"]').each(function(){jQuery(this).attr("disabled","disabled"),jQuery(this).after(jQuery(".wcml_lock_img").clone().removeClass("wcml_lock_img").show())});var e=["_stock_status","_shipping_class","_tax_class"];for(b=0;b<e.length;b++)jQuery('select[name^="variable'+e[b]+'"]').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(1==unlock_fields.file_paths){var f=["_wc_variation_file_names","_wc_variation_file_urls"];for(b=0;b<f.length;b++)jQuery('input[name^="'+f[b]+'"]').each(function(){jQuery(this).attr("readonly","readonly"),jQuery(this).after(jQuery(".wcml_lock_img").clone().removeClass("wcml_lock_img").show())});var g=["upload_file_button","insert","delete"];for(b=0;b<g.length;b++)jQuery("."+g[b]).attr("disabled","disabled"),jQuery("."+g[b]).after(jQuery(".wcml_lock_img").clone().removeClass("wcml_lock_img").show().css("float","right"))}}};
res/js/multi-currency.js CHANGED
@@ -67,11 +67,9 @@ jQuery( function($){
67
  $('#multi_currency_independent').change(function(){
68
 
69
  if($(this).attr('checked') == 'checked'){
70
- $('#currency-switcher').fadeIn();
71
- $('#multi-currency-per-language-details').fadeIn();
72
  }else{
73
- $('#multi-currency-per-language-details').fadeOut();
74
- $('#currency-switcher').fadeOut();
75
  }
76
 
77
  })
@@ -136,6 +134,11 @@ jQuery( function($){
136
  });
137
 
138
  WCML_Multi_Currency.currency_switcher_preview();
 
 
 
 
 
139
  },
140
  done: function() {
141
  ajaxLoader.remove();
@@ -224,6 +227,11 @@ jQuery( function($){
224
  $('#wcml_mc_options').before(response.currency_options);
225
 
226
  $('#wcml_currency_options_code_ option[value="'+currency+'"]').remove();
 
 
 
 
 
227
  }
228
 
229
  })
67
  $('#multi_currency_independent').change(function(){
68
 
69
  if($(this).attr('checked') == 'checked'){
70
+ $('#currency-switcher, #multi-currency-per-language-details, #online-exchange-rates').fadeIn();
 
71
  }else{
72
+ $('#currency-switcher, #multi-currency-per-language-details, #online-exchange-rates').fadeOut();
 
73
  }
74
 
75
  })
134
  });
135
 
136
  WCML_Multi_Currency.currency_switcher_preview();
137
+
138
+ if( $('.wcml-row-currency').length == 1 ){
139
+ $('#online-exchange-rates-no-currencies').next().hide();
140
+ $('#online-exchange-rates-no-currencies').show();
141
+ }
142
  },
143
  done: function() {
144
  ajaxLoader.remove();
227
  $('#wcml_mc_options').before(response.currency_options);
228
 
229
  $('#wcml_currency_options_code_ option[value="'+currency+'"]').remove();
230
+
231
+ if( $('#online-exchange-rates-no-currencies').is(':visible') ){
232
+ $('#online-exchange-rates-no-currencies').hide();
233
+ $('#online-exchange-rates-no-currencies').next().show();
234
+ }
235
  }
236
 
237
  })
res/js/multi-currency.min.js CHANGED
@@ -1 +1 @@
1
- jQuery(function(a){WCML_Multi_Currency={_currency_languages_saving:0,init:function(){a(document).ready(function(){WCML_Multi_Currency.setup_multi_currency_toggle(),a(document).on("change",".currency_code select",WCML_Multi_Currency.select_currency),a(document).on("click",".delete_currency",WCML_Multi_Currency.delete_currency),a(document).on("click",".wcml_currency_options .currency_options_save",WCML_Multi_Currency.save_currency),a(document).on("click",".js-display-tooltip",WCML_Multi_Currency.tooltip),a(document).on("click",".currency_languages a.otgs-ico-no",WCML_Multi_Currency.enable_currency_for_language),a(document).on("click",".currency_languages a.otgs-ico-yes",WCML_Multi_Currency.disable_currency_for_language),a(document).on("change",".default_currency select",WCML_Multi_Currency.change_default_currency),WCML_Multi_Currency.setup_currencies_sorting(),a(document).on("click",'input[name="currency_switcher_style"]',WCML_Multi_Currency.update_currency_switcher_style),a(document).on("change","#wcml_curr_sel_orientation",WCML_Multi_Currency.set_currency_switcher_orientation),a(document).on("keyup",'input[name="wcml_curr_template"]',WCML_Multi_Currency.setup_currency_switcher_template_keyup),a(document).on("change",'input[name="wcml_curr_template"]',WCML_Multi_Currency.setup_currency_switcher_template_change),a(document).on("change",".currency_option_position",WCML_Multi_Currency.price_preview),a(document).on("change",".currency_option_thousand_sep",WCML_Multi_Currency.price_preview),a(document).on("change",".currency_option_decimal_sep",WCML_Multi_Currency.price_preview),a(document).on("change",".currency_option_decimals",WCML_Multi_Currency.price_preview),a(document).on("change",".currency_code select",WCML_Multi_Currency.price_preview),a("#wcml_mc_options").length&&(WCML_Multi_Currency.wcml_mc_form_submitted=!1,WCML_Multi_Currency.read_form_fields_status(),window.onbeforeunload=function(b){return!WCML_Multi_Currency.wcml_mc_form_submitted&&WCML_Multi_Currency.form_fields_changed()||WCML_Multi_Currency.is_update_currency_lang_in_progress()?a("#wcml_warn_message").val():void 0},a("#wcml_mc_options").on("submit",function(){WCML_Multi_Currency.wcml_mc_form_submitted=!0}))})},setup_multi_currency_toggle:function(){a("#multi_currency_independent").change(function(){"checked"==a(this).attr("checked")?(a("#currency-switcher").fadeIn(),a("#multi-currency-per-language-details").fadeIn()):(a("#multi-currency-per-language-details").fadeOut(),a("#currency-switcher").fadeOut())})},select_currency:function(){var b=a(this).closest(".wcml_currency_options"),c=b.find(".wcml-dialog-close-button");c.attr("data-currency",a(this).val()),c.attr("data-symbol",a(this).find("option:selected").attr("data-symbol")),b.find(".this-currency").html(a(this).val())},delete_currency:function(b){b.preventDefault();var c=!1,d=a(this).data("currency"),e=a(this).data("currency_name"),f=a(this).data("currency_symbol");if(a(".currency_lang_table .wcml-row-currency-lang:first .currency_languages").each(function(){return WCML_Multi_Currency.check_currency_language(a(this).find("li").data("lang"),d)?void 0:(c=!0,!1)}),!c){a("#currency_row_"+d+" .currency_action_update").hide();var g=a('<span class="spinner" style="visibility: visible;margin:0;">');return a(this).hide(),a(this).parent().append(g).show(),a.ajax({type:"post",url:ajaxurl,data:{action:"wcml_delete_currency",wcml_nonce:a("#del_currency_nonce").val(),code:d},success:function(b){a("#currency_row_"+d).remove(),a("#currency_row_langs_"+d).remove(),a("#currency_row_del_"+d).remove(),a("#wcml_currencies_order .wcml_currencies_order_"+d).remove(),a("#wcml_currency_options_code_").prepend('<option data-symbol="'+f+'" value="'+d+'">'+e+"</option>"),a("#wcml_currency_options_code_").val(d).trigger("change"),a("#currency-lang-table").find("tr.default_currency select").each(function(){a(this).find("option[value='"+d+"']").remove()}),WCML_Multi_Currency.currency_switcher_preview()},done:function(){g.remove()}}),!1}},save_currency:function(){var b=a(this).closest(".wcml-dialog-container"),c=WCML_Multi_Currency.check_on_numeric(b,".ext_rate"),d=WCML_Multi_Currency.check_on_numeric(b,".currency_option_decimals"),e=WCML_Multi_Currency.check_on_numeric(b,".abstract_amount");if(c||d||e)return!1;a(".wcml-currency-options-dialog :submit, .wcml-currency-options-dialog :button").prop("disabled",!0);var f=b.find('[name="currency_options[code]"]').val(),g=a('<span class="spinner" style="visibility:visible;position:absolute;margin-left:10px;"></span>');return g.show(),a(this).parent().prepend(g),a.ajax({url:ajaxurl,type:"POST",dataType:"json",data:b.find('[name^="currency_options"]').serialize()+"&action=wcml_save_currency&wcml_nonce="+jQuery("#wcml_save_currency_nonce").val(),success:function(c){if(b.find(".wcml-dialog-close-button").trigger("click"),WCML_Multi_Currency.currency_switcher_preview(),0==a("#currency_row_"+f).length){var d=a("#currency-table tr.wcml-row-currency:last").clone();d.attr("id","currency_row_"+f);var e=d.find(".wcml-col-edit a");e.attr("data-content","wcml_currency_options_"+f),e.attr("data-currency",f),e.data("dialog","wcml_currency_options_"+f),e.removeClass("hidden"),a("#currency-table").find("tr.default_currency").before(d);var d=a("#currency-lang-table tr.wcml-row-currency-lang:last").clone();d.attr("id","currency_row_langs_"+f),a("#currency-lang-table").find("tr.default_currency").before(d),d.find(".on a").each(function(){a(this).attr("data-currency",f)}),a("#currency-lang-table").find("tr.default_currency select").each(function(){a(this).append('<option value="'+f+'">'+f+"</option>")}),a("#wcml_currencies_order").append('<li class="wcml_currencies_order_'+f+' ui-sortable-handle" cur="'+f+'">'+c.currency_name_formatted+"</li>");var d=a("#currency-delete-table tr.wcml-row-currency-del:last").clone();d.attr("id","currency_row_del_"+f);var g=d.find(".delete_currency");g.removeClass("hidden"),g.attr("data-currency",f),g.attr("data-currency_name",c.currency_name),g.attr("data-currency_symbol",c.currency_symbol),a("#currency-delete-table").find("tr.default_currency").before(d)}a("#currency_row_"+f+" .wcml-col-currency").html(c.currency_name_formatted),a("#currency_row_"+f+" .wcml-col-rate").html(c.currency_meta_info),a("#wcml_currency_options_"+f).remove(),a("#wcml_mc_options").before(c.currency_options),a('#wcml_currency_options_code_ option[value="'+f+'"]').remove()}}),!1},check_on_numeric:function(b,c){var d=a('<span class="wcml-error">');return WCML_Multi_Currency.is_number(b.find(c).val())?(b.find(c).parent().find(".wcml-error").size()>0&&b.find(c).parent().find(".wcml-error").remove(),!1):(0==b.find(c).parent().find(".wcml-error").size()&&(b.find(c).parent().append(d),d.text(b.find(c).data("message"))),!0)},tooltip:function(){var b=a(this);a(".wp-pointer").fadeOut(100),a(this).pointer({content:"<h3>"+b.data("header")+"</h3><p>"+b.data("content")+"</p>",position:{edge:"left",align:"center",offset:"15 0"}}).pointer("open")},enable_currency_for_language:function(b){if(WCML_Multi_Currency.is_update_currency_lang_in_progress())return!1;b.preventDefault(),a(this).addClass("spinner").removeClass("otgs-ico-no").css("visibility","visible");a(this).closest("tr")[0].rowIndex;a('.default_currency select[rel="'+a(this).data("language")+'"]').append('<option value="'+a(this).data("currency")+'">'+a(this).data("currency")+"</option>"),WCML_Multi_Currency.update_currency_lang(a(this),1,0);var c=a(this).data("title-alt");a(this).data("title-alt",a(this).attr("title")),a(this).attr("title",c)},disable_currency_for_language:function(b){if(WCML_Multi_Currency.is_update_currency_lang_in_progress())return!1;b.preventDefault(),a(this).addClass("spinner").removeClass("otgs-ico-yes").css("visibility","visible");var c=a(this).data("language");if(!WCML_Multi_Currency.check_currency_language(c))return void a(this).removeClass("spinner").addClass("otgs-ico-yes");a(this).closest("tr")[0].rowIndex;a('.currency_languages select[rel="'+a(this).data("language")+'"]').val()==a(this).data("currency")?WCML_Multi_Currency.update_currency_lang(a(this),0,1):WCML_Multi_Currency.update_currency_lang(a(this),0,0),a('.default_currency select[rel="'+a(this).data("language")+'"] option[value="'+a(this).data("currency")+'"]').remove();var d=a(this).data("title-alt");a(this).data("title-alt",a(this).attr("title")),a(this).attr("title",d)},check_currency_language:function(b,c){var d=a('#currency-lang-table a.otgs-ico-yes[data-language="'+b+'"]');return c&&(d=a('#currency-lang-table a.otgs-ico-yes[data-language="'+b+'"]:not([data-currency="'+c+'"]')),0==d.length?(alert(a("#wcml_warn_disable_language_massage").val()),!1):!0},is_update_currency_lang_in_progress:function(){var a="undefined"!=typeof WCML_Multi_Currency._update_currency_lang_sync_flag&&1==WCML_Multi_Currency._update_currency_lang_sync_flag;return a},set_update_currency_lang_in_progress:function(a){WCML_Multi_Currency._update_currency_lang_sync_flag=a},update_currency_lang:function(b,c,d){WCML_Multi_Currency._currency_languages_saving++,a("#wcml_mc_options :submit").attr("disabled","disabled"),a('input[name="wcml_mc_options"]').attr("disabled","disabled");var e=b.data("language"),f=b.data("currency");discard=!0,WCML_Multi_Currency.set_update_currency_lang_in_progress(1),a.ajax({type:"post",url:ajaxurl,data:{action:"wcml_update_currency_lang",value:c,lang:e,code:f,wcml_nonce:a("#update_currency_lang_nonce").val()},success:function(){d&&WCML_Multi_Currency.update_default_currency(e,0)},complete:function(){a('input[name="wcml_mc_options"]').removeAttr("disabled"),discard=!1,b.removeClass("spinner").css("visibility","visible"),c?b.addClass("otgs-ico-yes"):b.addClass("otgs-ico-no"),WCML_Multi_Currency._currency_languages_saving--,0==WCML_Multi_Currency._currency_languages_saving&&a("#wcml_mc_options :submit").removeAttr("disabled"),WCML_Multi_Currency.set_update_currency_lang_in_progress(0)}})},change_default_currency:function(){WCML_Multi_Currency.update_default_currency(a(this).attr("rel"),a(this).val(),a(this))},update_default_currency:function(b,c,d){if(a("#wcml_mc_options_submit").attr("disabled","disabled"),d){var e=a('<span class="spinner" style="visibility: visible;float:none;position: absolute">');d.parent().append(e)}discard=!0,a.ajax({type:"post",url:ajaxurl,data:{action:"wcml_update_default_currency",lang:b,code:c,wcml_nonce:a("#wcml_update_default_currency_nonce").val()},complete:function(){discard=!1,a("#wcml_mc_options_submit").removeAttr("disabled"),d&&d.parent().find(".spinner").remove()}})},is_number:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},setup_currencies_sorting:function(){a("#wcml_currencies_order").sortable({update:function(){a(".wcml_currencies_order_ajx_resp").fadeIn();var b=[];a("#wcml_currencies_order").find("li").each(function(){b.push(a(this).attr("cur"))}),a.ajax({type:"POST",url:ajaxurl,dataType:"json",data:{action:"wcml_currencies_order",wcml_nonce:a("#wcml_currencies_order_order_nonce").val(),order:b.join(";")},success:function(a){fadeInAjxResp(".wcml_currencies_order_ajx_resp",a.message),WCML_Multi_Currency.currency_switcher_preview()}})}})},currency_switcher_preview:function(){var b=a('input[name="wcml_curr_template"]').val();b||(b=a("#currency_switcher_default").val());var c=a('<span class="spinner" style="visibility: visible;">');a("#wcml_curr_sel_preview").html(c),a.ajax({type:"POST",url:ajaxurl,data:{action:"wcml_currencies_switcher_preview",wcml_nonce:a("#wcml_currencies_switcher_preview_nonce").val(),switcher_type:a('input[name="currency_switcher_style"]:checked').val(),orientation:a("#wcml_curr_sel_orientation").val(),template:b},success:function(b){a("#wcml_curr_sel_preview").html(b)}})},update_currency_switcher_style:function(b){"list"==a(this).val()?a("#wcml_curr_sel_orientation_list_wrap").show():a("#wcml_curr_sel_orientation_list_wrap").hide(),WCML_Multi_Currency.currency_switcher_preview()},set_currency_switcher_orientation:function(a){WCML_Multi_Currency.currency_switcher_preview()},setup_currency_switcher_template_keyup:function(b){discard=!0,a(this).closest(".wcml-section").find(".button-wrap input").css("border-color","#1e8cbe"),WCML_Multi_Currency.currency_switcher_preview()},setup_currency_switcher_template_change:function(b){a(this).val()||a('input[name="wcml_curr_template"]').val(a("#currency_switcher_default").val())},price_preview:function(){var b=a(this).closest(".wcml_currency_options"),c=b.find(".currency_option_position").val(),d=b.find(".currency_option_thousand_sep").val(),d=b.find(".currency_option_thousand_sep").val(),e=b.find(".currency_option_decimal_sep").val(),f=a(this).closest(".wcml_currency_options").find(".wcml-dialog-close-button").attr("data-symbol"),g="56789".substr(0,b.find(".currency_option_decimals").val());""==g&&(e="");var h="";switch(c){case"left":h="{symbol}1{thousand_sep}234{decimal_sep}{decimals}";break;case"right":h="1{thousand_sep}234{decimal_sep}{decimals}{symbol}";break;case"left_space":h="{symbol}&nbsp;1{thousand_sep}234{decimal_sep}{decimals}";break;case"right_space":h="1{thousand_sep}234{decimal_sep}{decimals}&nbsp;{symbol}"}var i=h.replace(/\{symbol\}/,f).replace(/\{thousand_sep\}/,d).replace(/\{decimal_sep\}/,e).replace(/\{decimals\}/,g);return b.find(".wcml-co-preview-value").html(i),!1},read_form_fields_status:function(){this.mc_form_status=a("#wcml_mc_options").serialize()},form_fields_changed:function(){return this.mc_form_status!=a("#wcml_mc_options").serialize()}},WCML_Multi_Currency.init()});
1
+ jQuery(function(a){WCML_Multi_Currency={_currency_languages_saving:0,init:function(){a(document).ready(function(){WCML_Multi_Currency.setup_multi_currency_toggle(),a(document).on("change",".currency_code select",WCML_Multi_Currency.select_currency),a(document).on("click",".delete_currency",WCML_Multi_Currency.delete_currency),a(document).on("click",".wcml_currency_options .currency_options_save",WCML_Multi_Currency.save_currency),a(document).on("click",".js-display-tooltip",WCML_Multi_Currency.tooltip),a(document).on("click",".currency_languages a.otgs-ico-no",WCML_Multi_Currency.enable_currency_for_language),a(document).on("click",".currency_languages a.otgs-ico-yes",WCML_Multi_Currency.disable_currency_for_language),a(document).on("change",".default_currency select",WCML_Multi_Currency.change_default_currency),WCML_Multi_Currency.setup_currencies_sorting(),a(document).on("click",'input[name="currency_switcher_style"]',WCML_Multi_Currency.update_currency_switcher_style),a(document).on("change","#wcml_curr_sel_orientation",WCML_Multi_Currency.set_currency_switcher_orientation),a(document).on("keyup",'input[name="wcml_curr_template"]',WCML_Multi_Currency.setup_currency_switcher_template_keyup),a(document).on("change",'input[name="wcml_curr_template"]',WCML_Multi_Currency.setup_currency_switcher_template_change),a(document).on("change",".currency_option_position",WCML_Multi_Currency.price_preview),a(document).on("change",".currency_option_thousand_sep",WCML_Multi_Currency.price_preview),a(document).on("change",".currency_option_decimal_sep",WCML_Multi_Currency.price_preview),a(document).on("change",".currency_option_decimals",WCML_Multi_Currency.price_preview),a(document).on("change",".currency_code select",WCML_Multi_Currency.price_preview),a("#wcml_mc_options").length&&(WCML_Multi_Currency.wcml_mc_form_submitted=!1,WCML_Multi_Currency.read_form_fields_status(),window.onbeforeunload=function(b){return!WCML_Multi_Currency.wcml_mc_form_submitted&&WCML_Multi_Currency.form_fields_changed()||WCML_Multi_Currency.is_update_currency_lang_in_progress()?a("#wcml_warn_message").val():void 0},a("#wcml_mc_options").on("submit",function(){WCML_Multi_Currency.wcml_mc_form_submitted=!0}))})},setup_multi_currency_toggle:function(){a("#multi_currency_independent").change(function(){"checked"==a(this).attr("checked")?a("#currency-switcher, #multi-currency-per-language-details, #online-exchange-rates").fadeIn():a("#currency-switcher, #multi-currency-per-language-details, #online-exchange-rates").fadeOut()})},select_currency:function(){var b=a(this).closest(".wcml_currency_options"),c=b.find(".wcml-dialog-close-button");c.attr("data-currency",a(this).val()),c.attr("data-symbol",a(this).find("option:selected").attr("data-symbol")),b.find(".this-currency").html(a(this).val())},delete_currency:function(b){b.preventDefault();var c=!1,d=a(this).data("currency"),e=a(this).data("currency_name"),f=a(this).data("currency_symbol");if(a(".currency_lang_table .wcml-row-currency-lang:first .currency_languages").each(function(){return WCML_Multi_Currency.check_currency_language(a(this).find("li").data("lang"),d)?void 0:(c=!0,!1)}),!c){a("#currency_row_"+d+" .currency_action_update").hide();var g=a('<span class="spinner" style="visibility: visible;margin:0;">');return a(this).hide(),a(this).parent().append(g).show(),a.ajax({type:"post",url:ajaxurl,data:{action:"wcml_delete_currency",wcml_nonce:a("#del_currency_nonce").val(),code:d},success:function(b){a("#currency_row_"+d).remove(),a("#currency_row_langs_"+d).remove(),a("#currency_row_del_"+d).remove(),a("#wcml_currencies_order .wcml_currencies_order_"+d).remove(),a("#wcml_currency_options_code_").prepend('<option data-symbol="'+f+'" value="'+d+'">'+e+"</option>"),a("#wcml_currency_options_code_").val(d).trigger("change"),a("#currency-lang-table").find("tr.default_currency select").each(function(){a(this).find("option[value='"+d+"']").remove()}),WCML_Multi_Currency.currency_switcher_preview(),1==a(".wcml-row-currency").length&&(a("#online-exchange-rates-no-currencies").next().hide(),a("#online-exchange-rates-no-currencies").show())},done:function(){g.remove()}}),!1}},save_currency:function(){var b=a(this).closest(".wcml-dialog-container"),c=WCML_Multi_Currency.check_on_numeric(b,".ext_rate"),d=WCML_Multi_Currency.check_on_numeric(b,".currency_option_decimals"),e=WCML_Multi_Currency.check_on_numeric(b,".abstract_amount");if(c||d||e)return!1;a(".wcml-currency-options-dialog :submit, .wcml-currency-options-dialog :button").prop("disabled",!0);var f=b.find('[name="currency_options[code]"]').val(),g=a('<span class="spinner" style="visibility:visible;position:absolute;margin-left:10px;"></span>');return g.show(),a(this).parent().prepend(g),a.ajax({url:ajaxurl,type:"POST",dataType:"json",data:b.find('[name^="currency_options"]').serialize()+"&action=wcml_save_currency&wcml_nonce="+jQuery("#wcml_save_currency_nonce").val(),success:function(c){if(b.find(".wcml-dialog-close-button").trigger("click"),WCML_Multi_Currency.currency_switcher_preview(),0==a("#currency_row_"+f).length){var d=a("#currency-table tr.wcml-row-currency:last").clone();d.attr("id","currency_row_"+f);var e=d.find(".wcml-col-edit a");e.attr("data-content","wcml_currency_options_"+f),e.attr("data-currency",f),e.data("dialog","wcml_currency_options_"+f),e.removeClass("hidden"),a("#currency-table").find("tr.default_currency").before(d);var d=a("#currency-lang-table tr.wcml-row-currency-lang:last").clone();d.attr("id","currency_row_langs_"+f),a("#currency-lang-table").find("tr.default_currency").before(d),d.find(".on a").each(function(){a(this).attr("data-currency",f)}),a("#currency-lang-table").find("tr.default_currency select").each(function(){a(this).append('<option value="'+f+'">'+f+"</option>")}),a("#wcml_currencies_order").append('<li class="wcml_currencies_order_'+f+' ui-sortable-handle" cur="'+f+'">'+c.currency_name_formatted+"</li>");var d=a("#currency-delete-table tr.wcml-row-currency-del:last").clone();d.attr("id","currency_row_del_"+f);var g=d.find(".delete_currency");g.removeClass("hidden"),g.attr("data-currency",f),g.attr("data-currency_name",c.currency_name),g.attr("data-currency_symbol",c.currency_symbol),a("#currency-delete-table").find("tr.default_currency").before(d)}a("#currency_row_"+f+" .wcml-col-currency").html(c.currency_name_formatted),a("#currency_row_"+f+" .wcml-col-rate").html(c.currency_meta_info),a("#wcml_currency_options_"+f).remove(),a("#wcml_mc_options").before(c.currency_options),a('#wcml_currency_options_code_ option[value="'+f+'"]').remove(),a("#online-exchange-rates-no-currencies").is(":visible")&&(a("#online-exchange-rates-no-currencies").hide(),a("#online-exchange-rates-no-currencies").next().show())}}),!1},check_on_numeric:function(b,c){var d=a('<span class="wcml-error">');return WCML_Multi_Currency.is_number(b.find(c).val())?(b.find(c).parent().find(".wcml-error").size()>0&&b.find(c).parent().find(".wcml-error").remove(),!1):(0==b.find(c).parent().find(".wcml-error").size()&&(b.find(c).parent().append(d),d.text(b.find(c).data("message"))),!0)},tooltip:function(){var b=a(this);a(".wp-pointer").fadeOut(100),a(this).pointer({content:"<h3>"+b.data("header")+"</h3><p>"+b.data("content")+"</p>",position:{edge:"left",align:"center",offset:"15 0"}}).pointer("open")},enable_currency_for_language:function(b){if(WCML_Multi_Currency.is_update_currency_lang_in_progress())return!1;b.preventDefault(),a(this).addClass("spinner").removeClass("otgs-ico-no").css("visibility","visible");a(this).closest("tr")[0].rowIndex;a('.default_currency select[rel="'+a(this).data("language")+'"]').append('<option value="'+a(this).data("currency")+'">'+a(this).data("currency")+"</option>"),WCML_Multi_Currency.update_currency_lang(a(this),1,0);var c=a(this).data("title-alt");a(this).data("title-alt",a(this).attr("title")),a(this).attr("title",c)},disable_currency_for_language:function(b){if(WCML_Multi_Currency.is_update_currency_lang_in_progress())return!1;b.preventDefault(),a(this).addClass("spinner").removeClass("otgs-ico-yes").css("visibility","visible");var c=a(this).data("language");if(!WCML_Multi_Currency.check_currency_language(c))return void a(this).removeClass("spinner").addClass("otgs-ico-yes");a(this).closest("tr")[0].rowIndex;a('.currency_languages select[rel="'+a(this).data("language")+'"]').val()==a(this).data("currency")?WCML_Multi_Currency.update_currency_lang(a(this),0,1):WCML_Multi_Currency.update_currency_lang(a(this),0,0),a('.default_currency select[rel="'+a(this).data("language")+'"] option[value="'+a(this).data("currency")+'"]').remove();var d=a(this).data("title-alt");a(this).data("title-alt",a(this).attr("title")),a(this).attr("title",d)},check_currency_language:function(b,c){var d=a('#currency-lang-table a.otgs-ico-yes[data-language="'+b+'"]');return c&&(d=a('#currency-lang-table a.otgs-ico-yes[data-language="'+b+'"]:not([data-currency="'+c+'"]')),0==d.length?(alert(a("#wcml_warn_disable_language_massage").val()),!1):!0},is_update_currency_lang_in_progress:function(){var a="undefined"!=typeof WCML_Multi_Currency._update_currency_lang_sync_flag&&1==WCML_Multi_Currency._update_currency_lang_sync_flag;return a},set_update_currency_lang_in_progress:function(a){WCML_Multi_Currency._update_currency_lang_sync_flag=a},update_currency_lang:function(b,c,d){WCML_Multi_Currency._currency_languages_saving++,a("#wcml_mc_options :submit").attr("disabled","disabled"),a('input[name="wcml_mc_options"]').attr("disabled","disabled");var e=b.data("language"),f=b.data("currency");discard=!0,WCML_Multi_Currency.set_update_currency_lang_in_progress(1),a.ajax({type:"post",url:ajaxurl,data:{action:"wcml_update_currency_lang",value:c,lang:e,code:f,wcml_nonce:a("#update_currency_lang_nonce").val()},success:function(){d&&WCML_Multi_Currency.update_default_currency(e,0)},complete:function(){a('input[name="wcml_mc_options"]').removeAttr("disabled"),discard=!1,b.removeClass("spinner").css("visibility","visible"),c?b.addClass("otgs-ico-yes"):b.addClass("otgs-ico-no"),WCML_Multi_Currency._currency_languages_saving--,0==WCML_Multi_Currency._currency_languages_saving&&a("#wcml_mc_options :submit").removeAttr("disabled"),WCML_Multi_Currency.set_update_currency_lang_in_progress(0)}})},change_default_currency:function(){WCML_Multi_Currency.update_default_currency(a(this).attr("rel"),a(this).val(),a(this))},update_default_currency:function(b,c,d){if(a("#wcml_mc_options_submit").attr("disabled","disabled"),d){var e=a('<span class="spinner" style="visibility: visible;float:none;position: absolute">');d.parent().append(e)}discard=!0,a.ajax({type:"post",url:ajaxurl,data:{action:"wcml_update_default_currency",lang:b,code:c,wcml_nonce:a("#wcml_update_default_currency_nonce").val()},complete:function(){discard=!1,a("#wcml_mc_options_submit").removeAttr("disabled"),d&&d.parent().find(".spinner").remove()}})},is_number:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},setup_currencies_sorting:function(){a("#wcml_currencies_order").sortable({update:function(){a(".wcml_currencies_order_ajx_resp").fadeIn();var b=[];a("#wcml_currencies_order").find("li").each(function(){b.push(a(this).attr("cur"))}),a.ajax({type:"POST",url:ajaxurl,dataType:"json",data:{action:"wcml_currencies_order",wcml_nonce:a("#wcml_currencies_order_order_nonce").val(),order:b.join(";")},success:function(a){fadeInAjxResp(".wcml_currencies_order_ajx_resp",a.message),WCML_Multi_Currency.currency_switcher_preview()}})}})},currency_switcher_preview:function(){var b=a('input[name="wcml_curr_template"]').val();b||(b=a("#currency_switcher_default").val());var c=a('<span class="spinner" style="visibility: visible;">');a("#wcml_curr_sel_preview").html(c),a.ajax({type:"POST",url:ajaxurl,data:{action:"wcml_currencies_switcher_preview",wcml_nonce:a("#wcml_currencies_switcher_preview_nonce").val(),switcher_type:a('input[name="currency_switcher_style"]:checked').val(),orientation:a("#wcml_curr_sel_orientation").val(),template:b},success:function(b){a("#wcml_curr_sel_preview").html(b)}})},update_currency_switcher_style:function(b){"list"==a(this).val()?a("#wcml_curr_sel_orientation_list_wrap").show():a("#wcml_curr_sel_orientation_list_wrap").hide(),WCML_Multi_Currency.currency_switcher_preview()},set_currency_switcher_orientation:function(a){WCML_Multi_Currency.currency_switcher_preview()},setup_currency_switcher_template_keyup:function(b){discard=!0,a(this).closest(".wcml-section").find(".button-wrap input").css("border-color","#1e8cbe"),WCML_Multi_Currency.currency_switcher_preview()},setup_currency_switcher_template_change:function(b){a(this).val()||a('input[name="wcml_curr_template"]').val(a("#currency_switcher_default").val())},price_preview:function(){var b=a(this).closest(".wcml_currency_options"),c=b.find(".currency_option_position").val(),d=b.find(".currency_option_thousand_sep").val(),d=b.find(".currency_option_thousand_sep").val(),e=b.find(".currency_option_decimal_sep").val(),f=a(this).closest(".wcml_currency_options").find(".wcml-dialog-close-button").attr("data-symbol"),g="56789".substr(0,b.find(".currency_option_decimals").val());""==g&&(e="");var h="";switch(c){case"left":h="{symbol}1{thousand_sep}234{decimal_sep}{decimals}";break;case"right":h="1{thousand_sep}234{decimal_sep}{decimals}{symbol}";break;case"left_space":h="{symbol}&nbsp;1{thousand_sep}234{decimal_sep}{decimals}";break;case"right_space":h="1{thousand_sep}234{decimal_sep}{decimals}&nbsp;{symbol}"}var i=h.replace(/\{symbol\}/,f).replace(/\{thousand_sep\}/,d).replace(/\{decimal_sep\}/,e).replace(/\{decimals\}/,g);return b.find(".wcml-co-preview-value").html(i),!1},read_form_fields_status:function(){this.mc_form_status=a("#wcml_mc_options").serialize()},form_fields_changed:function(){return this.mc_form_status!=a("#wcml_mc_options").serialize()}},WCML_Multi_Currency.init()});
res/js/pointer.js ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ var WCML_Pointer = WCML_Pointer || {};
2
+
3
+ ( function( $ ) {
4
+ WCML_Pointer.openPointer = function( trigger ) {
5
+ var content = $( '#' + trigger.data( 'wcml-open-pointer' ) );
6
+ $( '.wcml-information-active-pointer' ).pointer( 'close' );
7
+
8
+ if( trigger.length ) {
9
+ trigger.addClass( 'wcml-information-active-pointer' );
10
+ trigger.pointer( {
11
+ pointerClass : 'wcml-information-pointer',
12
+ content: content.html(),
13
+ position: {
14
+ edge: 'bottom',
15
+ align: 'right'
16
+ },
17
+ buttons: function( event, t ) {
18
+ var button_close = $( '<a href="javascript:void(0);" class="notice-dismiss alignright"></a>' );
19
+ button_close.bind( 'click.pointer', function( e ) {
20
+ e.preventDefault();
21
+ t.element.pointer( 'close' );
22
+ });
23
+ return button_close;
24
+ },
25
+ show: function( event, t ){
26
+ t.pointer.css( 'marginLeft', '115px' );
27
+ t.pointer.css( 'z-index', '99999' );
28
+ },
29
+ close: function( event, t ){
30
+ t.pointer.css( 'marginLeft', '0' );
31
+ },
32
+ } ).pointer( 'open' );
33
+ }
34
+ }
35
+
36
+ $( 'body' ).on( 'click', '[data-wcml-open-pointer]', function() {
37
+ WCML_Pointer.openPointer( $( this ) );
38
+ } );
39
+
40
+ $( 'body' ).on( 'click', 'a', function() {
41
+ if( ! $(this).hasClass( 'wcml-pointer-link' ) ){
42
+ $( '.wcml-information-active-pointer' ).pointer( 'close' );
43
+ }
44
+ } );
45
+
46
+ } )( jQuery );
47
+
48
+ jQuery( document ).ready( function($) {
49
+
50
+ $('.wcml-pointer-block').each( function(){
51
+ var selector = $(this).data('selector');
52
+ if( selector ){
53
+ var insert_method = $(this).data('insert-method');
54
+ switch(insert_method){
55
+ case 'prepend':
56
+ $(this).prependTo( $( '#'+selector ) ).show();
57
+ break;
58
+ case 'append':
59
+ $(this).appendTo( $( '#'+selector ) ).show();
60
+ break;
61
+ default:
62
+ $(this).insertAfter( $( '#'+selector ) ).show();
63
+ }
64
+ }else{
65
+ $(this).show();
66
+ }
67
+ });
68
+
69
+ });
res/js/pointer.min.js ADDED
@@ -0,0 +1 @@
 
1
+ var WCML_Pointer=WCML_Pointer||{};!function(a){WCML_Pointer.openPointer=function(b){var c=a("#"+b.data("wcml-open-pointer"));a(".wcml-information-active-pointer").pointer("close"),b.length&&(b.addClass("wcml-information-active-pointer"),b.pointer({pointerClass:"wcml-information-pointer",content:c.html(),position:{edge:"bottom",align:"right"},buttons:function(b,c){var d=a('<a href="javascript:void(0);" class="notice-dismiss alignright"></a>');return d.bind("click.pointer",function(a){a.preventDefault(),c.element.pointer("close")}),d},show:function(a,b){b.pointer.css("marginLeft","115px"),b.pointer.css("z-index","99999")},close:function(a,b){b.pointer.css("marginLeft","0")}}).pointer("open"))},a("body").on("click","[data-wcml-open-pointer]",function(){WCML_Pointer.openPointer(a(this))}),a("body").on("click","a",function(){a(this).hasClass("wcml-pointer-link")||a(".wcml-information-active-pointer").pointer("close")})}(jQuery),jQuery(document).ready(function(a){a(".wcml-pointer-block").each(function(){var b=a(this).data("selector");if(b){var c=a(this).data("insert-method");switch(c){case"prepend":a(this).prependTo(a("#"+b)).show();break;case"append":a(this).appendTo(a("#"+b)).show();break;default:a(this).insertAfter(a("#"+b)).show()}}else a(this).show()})});
res/js/scripts.js CHANGED
@@ -58,73 +58,6 @@ jQuery(document).ready(function ($) {
58
 
59
  }
60
 
61
- $(document).on('click', '.js-tax-translation li a[href^="#ignore-"]', function () {
62
-
63
- disable_tax_translation_toggling();
64
-
65
- var taxonomy = $(this).attr('href').replace(/#ignore-/, '');
66
-
67
- var spinner = '<span class="spinner" style="visibility: visible; position: absolute" />';
68
- $(this).append(spinner);
69
-
70
- $.ajax({
71
- type: "post",
72
- url: ajaxurl,
73
- dataType: 'json',
74
- data: {
75
- action: "wcml_ingore_taxonomy_translation",
76
- taxonomy: taxonomy,
77
- wcml_nonce: $('#wcml_ingore_taxonomy_translation_nonce').val()
78
- },
79
- success: function (response) {
80
-
81
- if (response.html) {
82
- $('.js-tax-translation li.js-tax-translation-' + taxonomy).html(response.html);
83
-
84
- $('.js-tax-tab-' + taxonomy).removeAttr('title');
85
- $('.js-tax-tab-' + taxonomy + ' i.otgs-ico-warning').remove();
86
- }
87
-
88
- enable_tax_translation_toggling();
89
- }
90
- })
91
-
92
- return false;
93
- })
94
-
95
- $(document).on('click', '.js-tax-translation li a[href^="#unignore-"]', function () {
96
-
97
- disable_tax_translation_toggling();
98
-
99
- var taxonomy = $(this).attr('href').replace(/#unignore-/, '');
100
-
101
- var spinner = '<span class="spinner" style="visibility: visible; position: absolute" />';
102
- $(this).append(spinner);
103
-
104
- $.ajax({
105
- type: "post",
106
- url: ajaxurl,
107
- dataType: 'json',
108
- data: {
109
- action: "wcml_uningore_taxonomy_translation",
110
- taxonomy: taxonomy,
111
- wcml_nonce: $('#wcml_ingore_taxonomy_translation_nonce').val()
112
- },
113
- success: function (response) {
114
- if (response.html) {
115
- $('.js-tax-translation li.js-tax-translation-' + taxonomy).html(response.html);
116
- if (response.warn) {
117
- $('.js-tax-tab-' + taxonomy).append('<i class="otgs-ico-warning"></i>');
118
- }
119
-
120
- }
121
- enable_tax_translation_toggling();
122
- }
123
- })
124
-
125
- return false;
126
- })
127
-
128
  function disable_tax_translation_toggling() {
129
  $('.wcml-tax-translation-list .actions a')
130
  .bind('click', tax_translation_toggling_return_false)
58
 
59
  }
60
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  function disable_tax_translation_toggling() {
62
  $('.wcml-tax-translation-list .actions a')
63
  .bind('click', tax_translation_toggling_return_false)
res/js/scripts.min.js CHANGED
@@ -1 +1 @@
1
- jQuery(document).ready(function(a){function b(){a(".wcml-tax-translation-list .actions a").bind("click",d).css({cursor:"wait"})}function c(){a(".wcml-tax-translation-list .actions a").unbind("click",d).css({cursor:"pointer"})}function d(a){return a.preventDefault(),!1}var e=!1;window.onbeforeunload=function(b){if(e)return a("#wcml_warn_message").val()},a('.wcml-section input[type="submit"]').click(function(){e=!1}),a(".wcml_search").click(function(){window.location=a(".wcml_products_admin_url").val()+"&cat="+a(".wcml_product_category").val()+"&trst="+a(".wcml_translation_status").val()+"&st="+a(".wcml_product_status").val()+"&slang="+a(".wcml_translation_status_lang").val()}),a(".wcml_search_by_title").click(function(){window.location=a(".wcml_products_admin_url").val()+"&s="+a(".wcml_product_name").val()}),a(".wcml_reset_search").click(function(){window.location=a(".wcml_products_admin_url").val()}),"undefined"!=typeof TaxonomyTranslation&&(TaxonomyTranslation.views.TermView=TaxonomyTranslation.views.TermView.extend({initialize:function(){TaxonomyTranslation.views.TermView.__super__.initialize.apply(this,arguments),this.listenTo(this.model,"translationSaved",this.render_overlay)},render_overlay:function(){var b=TaxonomyTranslation.classes.taxonomy.get("taxonomy");a.ajax({type:"post",url:ajaxurl,dataType:"json",data:{action:"wcml_update_term_translated_warnings",taxonomy:b,wcml_nonce:a("#wcml_update_term_translated_warnings_nonce").val()},success:function(c){c.hide&&(c.is_attribute?(a(".tax-product-attributes").removeAttr("title"),a(".tax-product-attributes i.otgs-ico-warning").remove()):(a(".js-tax-tab-"+b).removeAttr("title"),a(".js-tax-tab-"+b+" i.otgs-ico-warning").remove()))}})}})),a(document).on("click",'.js-tax-translation li a[href^="#ignore-"]',function(){b();var d=a(this).attr("href").replace(/#ignore-/,""),e='<span class="spinner" style="visibility: visible; position: absolute" />';return a(this).append(e),a.ajax({type:"post",url:ajaxurl,dataType:"json",data:{action:"wcml_ingore_taxonomy_translation",taxonomy:d,wcml_nonce:a("#wcml_ingore_taxonomy_translation_nonce").val()},success:function(b){b.html&&(a(".js-tax-translation li.js-tax-translation-"+d).html(b.html),a(".js-tax-tab-"+d).removeAttr("title"),a(".js-tax-tab-"+d+" i.otgs-ico-warning").remove()),c()}}),!1}),a(document).on("click",'.js-tax-translation li a[href^="#unignore-"]',function(){b();var d=a(this).attr("href").replace(/#unignore-/,""),e='<span class="spinner" style="visibility: visible; position: absolute" />';return a(this).append(e),a.ajax({type:"post",url:ajaxurl,dataType:"json",data:{action:"wcml_uningore_taxonomy_translation",taxonomy:d,wcml_nonce:a("#wcml_ingore_taxonomy_translation_nonce").val()},success:function(b){b.html&&(a(".js-tax-translation li.js-tax-translation-"+d).html(b.html),b.warn&&a(".js-tax-tab-"+d).append('<i class="otgs-ico-warning"></i>')),c()}}),!1}),a(document).on("submit","#wcml_tt_sync_variations",function(){var b=a("#wcml_tt_sync_variations"),c=b.serialize();return b.find(".wcml_tt_spinner").fadeIn(),b.find("input[type=submit]").attr("disabled","disabled"),a.ajax({type:"post",url:ajaxurl,dataType:"json",data:c,success:function(a){b.find(".wcml_tt_sycn_preview").html(a.progress),a.go?(b.find("input[name=last_post_id]").val(a.last_post_id),b.find("input[name=languages_processed]").val(a.languages_processed),b.trigger("submit")):(b.find("input[name=last_post_id]").val(0),b.find(".wcml_tt_spinner").fadeOut(),b.find("input").removeAttr("disabled"),jQuery("#wcml_tt_sync_assignment").fadeOut(),jQuery("#wcml_tt_sync_desc").fadeOut())}}),!1}),a(document).on("submit","#wcml_tt_sync_assignment",function(){var b=a("#wcml_tt_sync_assignment"),c=b.serialize();return b.find(".wcml_tt_spinner").fadeIn(),b.find("input").attr("disabled","disabled"),a(".wcml_tt_sync_row").remove(),a.ajax({type:"POST",dataType:"json",url:ajaxurl,data:"action=wcml_tt_sync_taxonomies_in_content_preview&wcml_nonce="+a("#wcml_sync_taxonomies_in_content_preview_nonce").val()+"&"+c,success:function(a){b.find(".wcml_tt_spinner").fadeOut(),b.find("input").removeAttr("disabled"),a.errors?b.find(".errors").html(a.errors):(jQuery("#wcml_tt_sync_preview").html(a.html),jQuery("#wcml_tt_sync_assignment").fadeOut(),jQuery("#wcml_tt_sync_desc").fadeOut())}}),!1}),a(document).on("click","form.wcml_tt_do_sync a.submit",function(){var b=a("form.wcml_tt_do_sync"),c=b.serialize();return b.find(".wcml_tt_spinner").fadeIn(),b.find("input").attr("disabled","disabled"),jQuery.ajax({type:"POST",dataType:"json",url:ajaxurl,data:"action=wcml_tt_sync_taxonomies_in_content&wcml_nonce="+a("#wcml_sync_taxonomies_in_content_nonce").val()+"&"+c,success:function(a){b.find(".wcml_tt_spinner").fadeOut(),b.find("input").removeAttr("disabled"),a.errors?b.find(".errors").html(a.errors):b.closest(".wcml_tt_sync_row").html(a.html)}}),!1});new Array;a("#wcml_custom_exchange_rates").submit(function(){var b=a(this);return b.find(":submit").parent().prepend(icl_ajxloaderimg+"&nbsp;"),b.find(":submit").prop("disabled",!0),a.ajax({type:"post",dataType:"json",url:ajaxurl,data:b.serialize(),success:function(){b.find(":submit").prev().remove(),b.find(":submit").prop("disabled",!1)}}),!1}),a(document).on("click",".wcml_save_base",function(b){b.preventDefault();var c=a(this),d=a(this).closest(".wcml-dialog-container"),e="#wcml-edit-base-slug-"+c.attr("data-base")+"-"+c.attr("data-language")+"-link",f="#wcml-edit-base-slug-"+c.attr("data-base")+"-"+c.attr("data-language");a.ajax({type:"post",url:ajaxurl,dataType:"json",data:{action:"wcml_update_base_translation",base:c.attr("data-base"),base_value:d.find("#base-original").val(),base_translation:d.find("#base-translation").val(),language:c.attr("data-language"),wcml_nonce:a("#wcml_update_base_nonce").val()},success:function(b){a(f).remove(),a(e).find("i").remove(),a(e).append('<i class="otgs-ico-edit" >'),a(e).parent().prepend(b)}})}),a(document).on("click",".hide-rate-block",function(){var b=a(this).closest(".wcml-wrap");a(this).attr("disabled","disabled");var c=a('<span class="spinner" style="visibility: visible;">'),d=jQuery(this).data("setting");return a(this).parent().prepend(c),a(this).remove(),a.ajax({type:"post",url:ajaxurl,dataType:"json",data:{action:"wcml_update_setting_ajx",setting:d,value:1,nonce:a("#wcml_settings_nonce").val()},success:function(a){b.hide()}}),!1}),a(document).on("click","#term-table-sync-header",function(){a("#wcml_tt_sync_assignment").hide(),a("#wcml_tt_sync_desc").hide()}),a(document).on("click","#term-table-header",function(){a("#wcml_tt_sync_assignment").data("sync")&&(a("#wcml_tt_sync_assignment").show(),a("#wcml_tt_sync_desc").show())})});
1
+ jQuery(document).ready(function(a){var b=!1;window.onbeforeunload=function(c){return b?a("#wcml_warn_message").val():void 0},a('.wcml-section input[type="submit"]').click(function(){b=!1}),a(".wcml_search").click(function(){window.location=a(".wcml_products_admin_url").val()+"&cat="+a(".wcml_product_category").val()+"&trst="+a(".wcml_translation_status").val()+"&st="+a(".wcml_product_status").val()+"&slang="+a(".wcml_translation_status_lang").val()}),a(".wcml_search_by_title").click(function(){window.location=a(".wcml_products_admin_url").val()+"&s="+a(".wcml_product_name").val()}),a(".wcml_reset_search").click(function(){window.location=a(".wcml_products_admin_url").val()}),"undefined"!=typeof TaxonomyTranslation&&(TaxonomyTranslation.views.TermView=TaxonomyTranslation.views.TermView.extend({initialize:function(){TaxonomyTranslation.views.TermView.__super__.initialize.apply(this,arguments),this.listenTo(this.model,"translationSaved",this.render_overlay)},render_overlay:function(){var b=TaxonomyTranslation.classes.taxonomy.get("taxonomy");a.ajax({type:"post",url:ajaxurl,dataType:"json",data:{action:"wcml_update_term_translated_warnings",taxonomy:b,wcml_nonce:a("#wcml_update_term_translated_warnings_nonce").val()},success:function(c){c.hide&&(c.is_attribute?(a(".tax-product-attributes").removeAttr("title"),a(".tax-product-attributes i.otgs-ico-warning").remove()):(a(".js-tax-tab-"+b).removeAttr("title"),a(".js-tax-tab-"+b+" i.otgs-ico-warning").remove()))}})}})),a(document).on("submit","#wcml_tt_sync_variations",function(){var b=a("#wcml_tt_sync_variations"),c=b.serialize();return b.find(".wcml_tt_spinner").fadeIn(),b.find("input[type=submit]").attr("disabled","disabled"),a.ajax({type:"post",url:ajaxurl,dataType:"json",data:c,success:function(a){b.find(".wcml_tt_sycn_preview").html(a.progress),a.go?(b.find("input[name=last_post_id]").val(a.last_post_id),b.find("input[name=languages_processed]").val(a.languages_processed),b.trigger("submit")):(b.find("input[name=last_post_id]").val(0),b.find(".wcml_tt_spinner").fadeOut(),b.find("input").removeAttr("disabled"),jQuery("#wcml_tt_sync_assignment").fadeOut(),jQuery("#wcml_tt_sync_desc").fadeOut())}}),!1}),a(document).on("submit","#wcml_tt_sync_assignment",function(){var b=a("#wcml_tt_sync_assignment"),c=b.serialize();return b.find(".wcml_tt_spinner").fadeIn(),b.find("input").attr("disabled","disabled"),a(".wcml_tt_sync_row").remove(),a.ajax({type:"POST",dataType:"json",url:ajaxurl,data:"action=wcml_tt_sync_taxonomies_in_content_preview&wcml_nonce="+a("#wcml_sync_taxonomies_in_content_preview_nonce").val()+"&"+c,success:function(a){b.find(".wcml_tt_spinner").fadeOut(),b.find("input").removeAttr("disabled"),a.errors?b.find(".errors").html(a.errors):(jQuery("#wcml_tt_sync_preview").html(a.html),jQuery("#wcml_tt_sync_assignment").fadeOut(),jQuery("#wcml_tt_sync_desc").fadeOut())}}),!1}),a(document).on("click","form.wcml_tt_do_sync a.submit",function(){var b=a("form.wcml_tt_do_sync"),c=b.serialize();return b.find(".wcml_tt_spinner").fadeIn(),b.find("input").attr("disabled","disabled"),jQuery.ajax({type:"POST",dataType:"json",url:ajaxurl,data:"action=wcml_tt_sync_taxonomies_in_content&wcml_nonce="+a("#wcml_sync_taxonomies_in_content_nonce").val()+"&"+c,success:function(a){b.find(".wcml_tt_spinner").fadeOut(),b.find("input").removeAttr("disabled"),a.errors?b.find(".errors").html(a.errors):b.closest(".wcml_tt_sync_row").html(a.html)}}),!1});new Array;a("#wcml_custom_exchange_rates").submit(function(){var b=a(this);return b.find(":submit").parent().prepend(icl_ajxloaderimg+"&nbsp;"),b.find(":submit").prop("disabled",!0),a.ajax({type:"post",dataType:"json",url:ajaxurl,data:b.serialize(),success:function(){b.find(":submit").prev().remove(),b.find(":submit").prop("disabled",!1)}}),!1}),a(document).on("click",".wcml_save_base",function(b){b.preventDefault();var c=a(this),d=a(this).closest(".wcml-dialog-container"),e="#wcml-edit-base-slug-"+c.attr("data-base")+"-"+c.attr("data-language")+"-link",f="#wcml-edit-base-slug-"+c.attr("data-base")+"-"+c.attr("data-language");a.ajax({type:"post",url:ajaxurl,dataType:"json",data:{action:"wcml_update_base_translation",base:c.attr("data-base"),base_value:d.find("#base-original").val(),base_translation:d.find("#base-translation").val(),language:c.attr("data-language"),wcml_nonce:a("#wcml_update_base_nonce").val()},success:function(b){a(f).remove(),a(e).find("i").remove(),a(e).append('<i class="otgs-ico-edit" >'),a(e).parent().prepend(b)}})}),a(document).on("click",".hide-rate-block",function(){var b=a(this).closest(".wcml-wrap");a(this).attr("disabled","disabled");var c=a('<span class="spinner" style="visibility: visible;">'),d=jQuery(this).data("setting");return a(this).parent().prepend(c),a(this).remove(),a.ajax({type:"post",url:ajaxurl,dataType:"json",data:{action:"wcml_update_setting_ajx",setting:d,value:1,nonce:a("#wcml_settings_nonce").val()},success:function(a){b.hide()}}),!1}),a(document).on("click","#term-table-sync-header",function(){a("#wcml_tt_sync_assignment").hide(),a("#wcml_tt_sync_desc").hide()}),a(document).on("click","#term-table-header",function(){a("#wcml_tt_sync_assignment").data("sync")&&(a("#wcml_tt_sync_assignment").show(),a("#wcml_tt_sync_desc").show())})});
res/js/troubleshooting.min.js CHANGED
@@ -1 +1 @@
1
- function update_product_count(){jQuery.ajax({type:"post",url:ajaxurl,data:{action:"trbl_update_count",wcml_nonce:jQuery("#trbl_update_count_nonce").val()},success:function(a){jQuery(".var_status").each(function(){jQuery(this).html(a)}),jQuery("#count_prod_variat").val(a),jQuery("#wcml_sync_product_variations").is(":checked")?sync_variations():jQuery("#wcml_sync_gallery_images").is(":checked")?sync_product_gallery():jQuery("#wcml_sync_categories").is(":checked")?sync_product_categories():jQuery("#wcml_duplicate_terms").is(":checked")?duplicate_terms():(jQuery("#wcml_trbl").removeAttr("disabled"),jQuery(".spinner").hide(),jQuery("#wcml_trbl").next().fadeOut())}})}function sync_variations(){jQuery.ajax({type:"post",url:ajaxurl,data:{action:"trbl_sync_variations",wcml_nonce:jQuery("#trbl_sync_variations_nonce").val()},success:function(a){if(0==jQuery("#count_prod_variat").val())jQuery(".var_status").each(function(){jQuery(this).html(0)}),jQuery("#wcml_sync_gallery_images").is(":checked")?sync_product_gallery():jQuery("#wcml_sync_categories").is(":checked")?sync_product_categories():jQuery("#wcml_duplicate_terms").is(":checked")?duplicate_terms():(jQuery("#wcml_trbl").removeAttr("disabled"),jQuery(".spinner").hide(),jQuery("#wcml_trbl").next().fadeOut());else{var b=jQuery("#count_prod_variat").val()-3;b<0&&(b=0),jQuery(".var_status").each(function(){jQuery(this).html(b)}),jQuery("#count_prod_variat").val(b),sync_variations()}}})}function sync_product_gallery(){jQuery.ajax({type:"post",url:ajaxurl,data:{action:"trbl_gallery_images",wcml_nonce:jQuery("#trbl_gallery_images_nonce").val(),page:jQuery("#sync_galerry_page").val()},success:function(a){if(0==jQuery("#count_prod").val())jQuery("#wcml_sync_categories").is(":checked")?sync_product_categories():jQuery("#wcml_duplicate_terms").is(":checked")?duplicate_terms():(jQuery("#wcml_trbl").removeAttr("disabled"),jQuery(".spinner").hide(),jQuery("#wcml_trbl").next().fadeOut()),jQuery(".gallery_status").html(0);else{var b=jQuery("#count_prod").val()-5;b<0?b=0:jQuery("#sync_galerry_page").val(parseInt(jQuery("#sync_galerry_page").val())+1),jQuery(".gallery_status").html(b),jQuery("#count_prod").val(b),sync_product_gallery()}}})}function sync_product_categories(){jQuery.ajax({type:"post",url:ajaxurl,data:{action:"trbl_sync_categories",wcml_nonce:jQuery("#trbl_sync_categories_nonce").val(),page:jQuery("#sync_category_page").val()},success:function(a){if(0==jQuery("#count_categories").val())jQuery("#wcml_duplicate_terms").is(":checked")?duplicate_terms():(jQuery("#wcml_trbl").removeAttr("disabled"),jQuery(".spinner").hide(),jQuery("#wcml_trbl").next().fadeOut()),jQuery(".cat_status").html(0);else{var b=jQuery("#count_categories").val()-5;b<0?b=0:jQuery("#sync_category_page").val(parseInt(jQuery("#sync_category_page").val())+1),jQuery(".cat_status").html(b),jQuery("#count_categories").val(b),sync_product_categories()}}})}function duplicate_terms(){jQuery.ajax({type:"post",url:ajaxurl,data:{action:"trbl_duplicate_terms",wcml_nonce:jQuery("#trbl_duplicate_terms_nonce").val(),attr:jQuery("#attr_to_duplicate option:selected").val()},success:function(a){if(0==jQuery("#count_terms").val())jQuery("#wcml_trbl").removeAttr("disabled"),jQuery(".spinner").hide(),jQuery("#wcml_trbl").next().fadeOut(),jQuery(".attr_status").html(0);else{var b=jQuery("#count_terms").val()-5;b<0&&(b=0),jQuery(".attr_status").html(b),jQuery("#count_terms").val(b),duplicate_terms()}}})}jQuery(document).ready(function(){jQuery("#wcml_trbl").on("click",function(){var a=jQuery(this);a.attr("disabled","disabled"),jQuery(".spinner").css("display","inline-block").css("visibility","visible"),jQuery("#wcml_sync_update_product_count").is(":checked")?update_product_count():jQuery("#wcml_sync_product_variations").is(":checked")?sync_variations():jQuery("#wcml_sync_gallery_images").is(":checked")?sync_product_gallery():jQuery("#wcml_sync_categories").is(":checked")?sync_product_categories():jQuery("#wcml_duplicate_terms").is(":checked")&&duplicate_terms()}),jQuery("#attr_to_duplicate").on("change",function(){jQuery(".attr_status").html(jQuery(this).find("option:selected").attr("rel")),jQuery("#count_terms").val(jQuery(this).find("option:selected").attr("rel"))})});
1
+ function update_product_count(){jQuery.ajax({type:"post",url:ajaxurl,data:{action:"trbl_update_count",wcml_nonce:jQuery("#trbl_update_count_nonce").val()},success:function(a){jQuery(".var_status").each(function(){jQuery(this).html(a)}),jQuery("#count_prod_variat").val(a),jQuery("#wcml_sync_product_variations").is(":checked")?sync_variations():jQuery("#wcml_sync_gallery_images").is(":checked")?sync_product_gallery():jQuery("#wcml_sync_categories").is(":checked")?sync_product_categories():jQuery("#wcml_duplicate_terms").is(":checked")?duplicate_terms():(jQuery("#wcml_trbl").removeAttr("disabled"),jQuery(".spinner").hide(),jQuery("#wcml_trbl").next().fadeOut())}})}function sync_variations(){jQuery.ajax({type:"post",url:ajaxurl,data:{action:"trbl_sync_variations",wcml_nonce:jQuery("#trbl_sync_variations_nonce").val()},success:function(a){if(0==jQuery("#count_prod_variat").val())jQuery(".var_status").each(function(){jQuery(this).html(0)}),jQuery("#wcml_sync_gallery_images").is(":checked")?sync_product_gallery():jQuery("#wcml_sync_categories").is(":checked")?sync_product_categories():jQuery("#wcml_duplicate_terms").is(":checked")?duplicate_terms():(jQuery("#wcml_trbl").removeAttr("disabled"),jQuery(".spinner").hide(),jQuery("#wcml_trbl").next().fadeOut());else{var b=jQuery("#count_prod_variat").val()-3;0>b&&(b=0),jQuery(".var_status").each(function(){jQuery(this).html(b)}),jQuery("#count_prod_variat").val(b),sync_variations()}}})}function sync_product_gallery(){jQuery.ajax({type:"post",url:ajaxurl,data:{action:"trbl_gallery_images",wcml_nonce:jQuery("#trbl_gallery_images_nonce").val(),page:jQuery("#sync_galerry_page").val()},success:function(a){if(0==jQuery("#count_prod").val())jQuery("#wcml_sync_categories").is(":checked")?sync_product_categories():jQuery("#wcml_duplicate_terms").is(":checked")?duplicate_terms():(jQuery("#wcml_trbl").removeAttr("disabled"),jQuery(".spinner").hide(),jQuery("#wcml_trbl").next().fadeOut()),jQuery(".gallery_status").html(0);else{var b=jQuery("#count_prod").val()-5;0>b?b=0:jQuery("#sync_galerry_page").val(parseInt(jQuery("#sync_galerry_page").val())+1),jQuery(".gallery_status").html(b),jQuery("#count_prod").val(b),sync_product_gallery()}}})}function sync_product_categories(){jQuery.ajax({type:"post",url:ajaxurl,data:{action:"trbl_sync_categories",wcml_nonce:jQuery("#trbl_sync_categories_nonce").val(),page:jQuery("#sync_category_page").val()},success:function(a){if(0==jQuery("#count_categories").val())jQuery("#wcml_duplicate_terms").is(":checked")?duplicate_terms():(jQuery("#wcml_trbl").removeAttr("disabled"),jQuery(".spinner").hide(),jQuery("#wcml_trbl").next().fadeOut()),jQuery(".cat_status").html(0);else{var b=jQuery("#count_categories").val()-5;0>b?b=0:jQuery("#sync_category_page").val(parseInt(jQuery("#sync_category_page").val())+1),jQuery(".cat_status").html(b),jQuery("#count_categories").val(b),sync_product_categories()}}})}function duplicate_terms(){jQuery.ajax({type:"post",url:ajaxurl,data:{action:"trbl_duplicate_terms",wcml_nonce:jQuery("#trbl_duplicate_terms_nonce").val(),attr:jQuery("#attr_to_duplicate option:selected").val()},success:function(a){if(0==jQuery("#count_terms").val())jQuery("#wcml_trbl").removeAttr("disabled"),jQuery(".spinner").hide(),jQuery("#wcml_trbl").next().fadeOut(),jQuery(".attr_status").html(0);else{var b=jQuery("#count_terms").val()-5;0>b&&(b=0),jQuery(".attr_status").html(b),jQuery("#count_terms").val(b),duplicate_terms()}}})}jQuery(document).ready(function(){jQuery("#wcml_trbl").on("click",function(){var a=jQuery(this);a.attr("disabled","disabled"),jQuery(".spinner").css("display","inline-block").css("visibility","visible"),jQuery("#wcml_sync_update_product_count").is(":checked")?update_product_count():jQuery("#wcml_sync_product_variations").is(":checked")?sync_variations():jQuery("#wcml_sync_gallery_images").is(":checked")?sync_product_gallery():jQuery("#wcml_sync_categories").is(":checked")?sync_product_categories():jQuery("#wcml_duplicate_terms").is(":checked")&&duplicate_terms()}),jQuery("#attr_to_duplicate").on("change",function(){jQuery(".attr_status").html(jQuery(this).find("option:selected").attr("rel")),jQuery("#count_terms").val(jQuery(this).find("option:selected").attr("rel"))})});
res/js/wcml-multi-currency.js CHANGED
@@ -17,22 +17,29 @@ jQuery(document).ready(function(){
17
  });
18
 
19
 
20
- function wcml_load_currency( currency ){
21
  var ajax_loader = jQuery('<img style=\"margin-left:10px;\" width=\"16\" heigth=\"16\" src=\"' + wcml_mc_settings.wcml_spinner +'\" />')
22
  jQuery('.wcml_currency_switcher').attr('disabled', 'disabled');
23
  jQuery('.wcml_currency_switcher').after();
24
  ajax_loader.insertAfter(jQuery('.wcml_currency_switcher'));
 
 
 
25
  jQuery.ajax({
26
  type : 'post',
27
  url : woocommerce_params.ajax_url,
 
28
  data : {
29
  action: 'wcml_switch_currency',
30
  currency : currency,
 
31
  wcml_nonce: wcml_mc_settings.wcml_mc_nonce
32
  },
33
  success: function(response) {
34
- if(typeof response.error !== 'undefined'){
35
  alert(response.error);
 
 
36
  }else{
37
  jQuery('.wcml_currency_switcher').removeAttr('disabled');
38
  if(typeof wcml_mc_settings.w3tc !== 'undefined'){
@@ -47,7 +54,6 @@ function wcml_load_currency( currency ){
47
  var target_location = window.location.href;
48
  }
49
 
50
-
51
  window.location = target_location;
52
  }
53
  }
17
  });
18
 
19
 
20
+ function wcml_load_currency( currency, force_switch ){
21
  var ajax_loader = jQuery('<img style=\"margin-left:10px;\" width=\"16\" heigth=\"16\" src=\"' + wcml_mc_settings.wcml_spinner +'\" />')
22
  jQuery('.wcml_currency_switcher').attr('disabled', 'disabled');
23
  jQuery('.wcml_currency_switcher').after();
24
  ajax_loader.insertAfter(jQuery('.wcml_currency_switcher'));
25
+
26
+ if ( typeof force_switch === 'undefined') force_switch = 0;
27
+
28
  jQuery.ajax({
29
  type : 'post',
30
  url : woocommerce_params.ajax_url,
31
+ dataType: "json",
32
  data : {
33
  action: 'wcml_switch_currency',
34
  currency : currency,
35
+ force_switch: force_switch,
36
  wcml_nonce: wcml_mc_settings.wcml_mc_nonce
37
  },
38
  success: function(response) {
39
+ if(typeof response.error !== 'undefined') {
40
  alert(response.error);
41
+ }else if( typeof response.prevent_switching !== 'undefined' ){
42
+ jQuery('body').append( response.prevent_switching );
43
  }else{
44
  jQuery('.wcml_currency_switcher').removeAttr('disabled');
45
  if(typeof wcml_mc_settings.w3tc !== 'undefined'){
54
  var target_location = window.location.href;
55
  }
56
 
 
57
  window.location = target_location;
58
  }
59
  }
res/js/wcml-multi-currency.min.js CHANGED
@@ -1 +1 @@
1
- function wcml_load_currency(a){var b=jQuery('<img style="margin-left:10px;" width="16" heigth="16" src="'+wcml_mc_settings.wcml_spinner+'" />');jQuery(".wcml_currency_switcher").attr("disabled","disabled"),jQuery(".wcml_currency_switcher").after(),b.insertAfter(jQuery(".wcml_currency_switcher")),jQuery.ajax({type:"post",url:woocommerce_params.ajax_url,data:{action:"wcml_switch_currency",currency:a,wcml_nonce:wcml_mc_settings.wcml_mc_nonce},success:function(b){if("undefined"!=typeof b.error)alert(b.error);else{if(jQuery(".wcml_currency_switcher").removeAttr("disabled"),"undefined"!=typeof wcml_mc_settings.w3tc){var c=window.location.href;c=c.replace(/&wcmlc(\=[^&]*)?(?=&|$)|wcmlc(\=[^&]*)?(&|$)/,""),c=c.replace(/\?$/,"");var d=c.indexOf("?")!=-1?"&":"?",e=c+d+"wcmlc="+a}else var e=window.location.href;window.location=e}}})}jQuery(document).ready(function(){jQuery(document).on("change",".wcml_currency_switcher",function(){wcml_load_currency(jQuery(this).val())}),jQuery(document).on("click",".wcml_currency_switcher li",function(){jQuery(this).hasClass("wcml-active-currency")||wcml_load_currency(jQuery(this).attr("rel"))}),"undefined"!=typeof woocommerce_price_slider_params&&(woocommerce_price_slider_params.currency_symbol=wcml_mc_settings.current_currency.symbol)});
1
+ function wcml_load_currency(a,b){var c=jQuery('<img style="margin-left:10px;" width="16" heigth="16" src="'+wcml_mc_settings.wcml_spinner+'" />');jQuery(".wcml_currency_switcher").attr("disabled","disabled"),jQuery(".wcml_currency_switcher").after(),c.insertAfter(jQuery(".wcml_currency_switcher")),"undefined"==typeof b&&(b=0),jQuery.ajax({type:"post",url:woocommerce_params.ajax_url,dataType:"json",data:{action:"wcml_switch_currency",currency:a,force_switch:b,wcml_nonce:wcml_mc_settings.wcml_mc_nonce},success:function(b){if("undefined"!=typeof b.error)alert(b.error);else if("undefined"!=typeof b.prevent_switching)jQuery("body").append(b.prevent_switching);else{if(jQuery(".wcml_currency_switcher").removeAttr("disabled"),"undefined"!=typeof wcml_mc_settings.w3tc){var c=window.location.href;c=c.replace(/&wcmlc(\=[^&]*)?(?=&|$)|wcmlc(\=[^&]*)?(&|$)/,""),c=c.replace(/\?$/,"");var d=-1!=c.indexOf("?")?"&":"?",e=c+d+"wcmlc="+a}else var e=window.location.href;window.location=e}}})}jQuery(document).ready(function(){jQuery(document).on("change",".wcml_currency_switcher",function(){wcml_load_currency(jQuery(this).val())}),jQuery(document).on("click",".wcml_currency_switcher li",function(){jQuery(this).hasClass("wcml-active-currency")||wcml_load_currency(jQuery(this).attr("rel"))}),"undefined"!=typeof woocommerce_price_slider_params&&(woocommerce_price_slider_params.currency_symbol=wcml_mc_settings.current_currency.symbol)});
res/js/wcml-translation-editor.min.js CHANGED
@@ -1 +1 @@
1
- jQuery(function(a){var b={is_wcml_product:!1,field_views:null,footer_view:null,save_buttons_tip:null,init:function(){a(document).on("WPML_TM.editor.before_render",b.do_editor_before_render),a(document).on("WPML_TM.editor.ready",b.do_editor_ready)},show_file_paths_button:function(a,b){"file-url"===b.field.field_type.substr(0,8)&&b.$el.append('<div style="display: inline-block;width: 100%;"><button type="button" class="button-secondary wcml_file_paths_button" style="float: right;margin-right: 17px;">'+wcml_settings.strings.choose+"</button></div>")},show_downloadable_files_frame:function(b){var c,d,e,f=a(this);if(d=f.closest(".wpml-form-row").find(".translated_value"),e=d.val(),b.preventDefault(),c)return void c.open();var g=[new wp.media.controller.Library({library:wp.media.query(),multiple:!0,title:f.data("choose"),priority:20,filterable:"uploaded"})];c=wp.media.frames.downloadable_file=wp.media({title:f.data("choose"),library:{type:""},button:{text:f.data("update")},multiple:!0,states:g}),c.on("select",function(){var a=c.state().get("selection");a.map(function(a){a=a.toJSON(),a.url&&(e=a.url)}),d.val(e)}),c.on("ready",function(){c.uploader.options.uploader.params={type:"downloadable_product"}}),c.open()},update_slug:function(){var b=a("#job_field_title .js-translated-value").val(),c=a("#job_field_slug .js-translated-value");if(""!=b&&""==c.val()){var d=a("#icl_tm_editor input[name=job_id]").val();c.prop("readonly","on"),a.ajax({url:ajaxurl,type:"POST",dataType:"json",data:{action:"wcml_editor_auto_slug",title:b,job_id:d},success:function(b){c.val(b.slug),c.removeAttr("readonly"),a("#icl_tm_copy_link_slug").prop("disabled","on")}})}},do_editor_before_render:function(c,d){b.is_wcml_product="post_product"===d,b.is_wcml_product&&(a(document).on("WPML_TM.editor.field_view_ready",b.show_file_paths_button),a(document).on("WPML_TM.editor.field_update_ui",b.field_update_ui),a(document).on("click",".wcml_file_paths_button",b.show_downloadable_files_frame),a(document).on("blur","#job_field_title .js-translated-value",b.update_slug),a(document).on("focus","#job_field_slug .js-translated-value",b.update_slug),a(document).on("blur","#job_field_slug .js-translated-value",b.update_slug))},do_editor_ready:function(a,c,d,e){b.is_wcml_product&&(b.save_buttons_tip=WCML_Tooltip.add_before(".js-save-and-close",wcml_settings.strings.save_tooltip,"margin-right: 3px;"),b.field_views=d,b.footer_view=e,b.update_save_button_state(),b.check_variations_fields(),wcml_settings.hide_resign?b.footer_view.hideResignButton(!0):WCML_Tooltip.add_after(".js-resign",wcml_settings.strings.resign_tooltip,"margin-left:-12px;"))},update_save_button_state:function(){var a=["title","product_content","product_excerpt"],c=!0;_.each(b.field_views,function(d){var e=d.getTranslation();""!==e&&jQuery.inArray(d.getFieldType(),a)!==-1&&(c=!1,b.save_buttons_tip&&b.save_buttons_tip.hide())}),c&&b.save_buttons_tip.show(),b.footer_view.disableSaveButtons(c)},field_update_ui:function(a,c){b.update_save_button_state()},check_variations_fields:function(){var a=!1;jQuery('[id^="job_field_variation_desc"]').closest(".postbox").find(".original_value").each(function(){return""===jQuery(this).val()&&void(a=jQuery(this))}),a&&a.closest(".postbox").find(".button-link").click()}};b.init()});
1
+ jQuery(function(a){var b={is_wcml_product:!1,field_views:null,footer_view:null,save_buttons_tip:null,init:function(){a(document).on("WPML_TM.editor.before_render",b.do_editor_before_render),a(document).on("WPML_TM.editor.ready",b.do_editor_ready)},show_file_paths_button:function(a,b){"file-url"===b.field.field_type.substr(0,8)&&b.$el.append('<div style="display: inline-block;width: 100%;"><button type="button" class="button-secondary wcml_file_paths_button" style="float: right;margin-right: 17px;">'+wcml_settings.strings.choose+"</button></div>")},show_downloadable_files_frame:function(b){var c,d,e,f=a(this);if(d=f.closest(".wpml-form-row").find(".translated_value"),e=d.val(),b.preventDefault(),c)return void c.open();var g=[new wp.media.controller.Library({library:wp.media.query(),multiple:!0,title:f.data("choose"),priority:20,filterable:"uploaded"})];c=wp.media.frames.downloadable_file=wp.media({title:f.data("choose"),library:{type:""},button:{text:f.data("update")},multiple:!0,states:g}),c.on("select",function(){var a=c.state().get("selection");a.map(function(a){a=a.toJSON(),a.url&&(e=a.url)}),d.val(e)}),c.on("ready",function(){c.uploader.options.uploader.params={type:"downloadable_product"}}),c.open()},update_slug:function(){var b=a("#job_field_title .js-translated-value").val(),c=a("#job_field_slug .js-translated-value");if(""!=b&&""==c.val()){var d=a("#icl_tm_editor input[name=job_id]").val();c.prop("readonly","on"),a.ajax({url:ajaxurl,type:"POST",dataType:"json",data:{action:"wcml_editor_auto_slug",title:b,job_id:d},success:function(b){c.val(b.slug),c.removeAttr("readonly"),a("#icl_tm_copy_link_slug").prop("disabled","on")}})}},do_editor_before_render:function(c,d){b.is_wcml_product="post_product"===d,b.is_wcml_product&&(a(document).on("WPML_TM.editor.field_view_ready",b.show_file_paths_button),a(document).on("WPML_TM.editor.field_update_ui",b.field_update_ui),a(document).on("click",".wcml_file_paths_button",b.show_downloadable_files_frame),a(document).on("blur","#job_field_title .js-translated-value",b.update_slug),a(document).on("focus","#job_field_slug .js-translated-value",b.update_slug),a(document).on("blur","#job_field_slug .js-translated-value",b.update_slug))},do_editor_ready:function(a,c,d,e){b.is_wcml_product&&(b.save_buttons_tip=WCML_Tooltip.add_before(".js-save-and-close",wcml_settings.strings.save_tooltip,"margin-right: 3px;"),b.field_views=d,b.footer_view=e,b.update_save_button_state(),b.check_variations_fields(),wcml_settings.hide_resign?b.footer_view.hideResignButton(!0):WCML_Tooltip.add_after(".js-resign",wcml_settings.strings.resign_tooltip,"margin-left:-12px;"))},update_save_button_state:function(){var a=["title","product_content","product_excerpt"],c=!0;_.each(b.field_views,function(d){var e=d.getTranslation();""!==e&&-1!==jQuery.inArray(d.getFieldType(),a)&&(c=!1,b.save_buttons_tip&&b.save_buttons_tip.hide())}),c&&b.save_buttons_tip.show(),b.footer_view.disableSaveButtons(c)},field_update_ui:function(a,c){b.update_save_button_state()},check_variations_fields:function(){var a=!1;jQuery('[id^="job_field_variation_desc"]').closest(".postbox").find(".original_value").each(function(){return""!==jQuery(this).val()?!1:void(a=jQuery(this))}),a&&a.closest(".postbox").find(".button-link").click()}};b.init()});
res/scss/admin.scss CHANGED
@@ -4,4 +4,53 @@
4
  line-height: 15px;
5
  margin: 1px 0 0 2px;
6
  z-index: 26;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  }
4
  line-height: 15px;
5
  margin: 1px 0 0 2px;
6
  z-index: 26;
7
+ }
8
+
9
+
10
+ a.wcml-external-link {
11
+ padding-right: 15px;
12
+ }
13
+ a.wcml-external-link:after {
14
+ content: "\f504";
15
+ display: inline-block;
16
+ width: 15px;
17
+ margin-right: -15px;
18
+ font-size: 14px;
19
+ line-height: 18px;
20
+ font-family: dashicons;
21
+ text-decoration: none;
22
+ font-weight: normal;
23
+ font-style: normal;
24
+ vertical-align: top;
25
+ -webkit-font-smoothing: antialiased;
26
+ -moz-osx-font-smoothing: grayscale;
27
+ }
28
+ .wcml-pointer-inner .wcml-information-paragraph {
29
+ padding-right: 30px;
30
+ }
31
+ .wcml-pointer-inner .wp-pointer-buttons {
32
+ padding: 0;
33
+ }
34
+ .wcml-pointer-inner.wp-pointer-bottom .wp-pointer-arrow {
35
+ left: auto;
36
+ right: 50px;
37
+ }
38
+ .wcml-message-icon.wcml-table-cell,
39
+ .wcml-message-content.wcml-table-cell {
40
+ height: 100px;
41
+ }
42
+ .wcml-pointer-link{
43
+ position:relative;
44
+ text-decoration: none;
45
+ padding: 10px;
46
+ }
47
+ .wcml-cart-dialog button{
48
+ text-transform: capitalize;
49
+ }
50
+ div[data-selector="woocommerce_table_rate_title"] a,
51
+ div[data-selector="wpbody-content .woocommerce h2"] a{
52
+ padding: 10px 0 0 0;
53
+ }
54
+ #shipping_rates .shipping_label .wcml-pointer-link{
55
+ padding: 0;
56
  }
res/scss/currency-switcher.scss CHANGED
@@ -33,4 +33,22 @@ ul.wcml_currency_switcher {
33
  padding: 3px 10px;
34
  margin: 0;
35
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  }
33
  padding: 3px 10px;
34
  margin: 0;
35
  }
36
+ }
37
+
38
+ .exchange-rates-online-wrap,
39
+ .service-details-wrap {
40
+ padding-left: 24px;
41
+ .rtl & {
42
+ padding-left: 0;
43
+ padding-right: 24px;
44
+ }
45
+ }
46
+ .exchange-rate-service-website {
47
+ text-decoration: none;
48
+ .dashicons-external {
49
+ font-size: 14px;
50
+ width: 14px;
51
+ height: 14px;
52
+ vertical-align: -4px;
53
+ }
54
  }
res/scss/management.scss CHANGED
@@ -72,16 +72,14 @@
72
  }
73
  }
74
 
75
- .wcml-section-content .wcml-section-content-inner {
76
  margin: 0 0 20px 0;
77
  padding: 0 0 10px 0;
78
  border-bottom: 1px solid #ededed;
79
- float: left;
80
- width: 100%;
81
  }
82
 
83
  .wcml-section-header {
84
- width: 300px;
85
  float: left;
86
  h3 {
87
  font-weight: normal;
@@ -95,7 +93,7 @@
95
 
96
  .wcml-section-content {
97
  float: left;
98
- width: 570px;
99
  margin-left: 30px;
100
  }
101
 
@@ -148,14 +146,16 @@
148
  }
149
  input {
150
  margin: 0 !important;
151
- width: 70px;
152
  }
153
  .wcml-co-set-rate {
154
  display: inline-block;
155
  padding: 4px $margin-sm $margin-xs $margin-sm;
 
156
  }
157
  small {
158
  display: block;
 
159
  }
160
  }
161
  .wcml-co-help-link {
@@ -183,7 +183,7 @@
183
 
184
  table.widefat.currency_table {
185
  float: left;
186
- width: 300px;
187
  border-right: none;
188
 
189
  td.wcml-col-currency,
@@ -195,7 +195,7 @@ table.widefat.currency_table {
195
 
196
  td.wcml-col-currency {
197
  .truncate {
198
- max-width: 145px;
199
  display: block;
200
  }
201
  small {
@@ -324,7 +324,7 @@ table.widefat.currency_lang_table {
324
  }
325
 
326
  .currency_wrap {
327
- width: calc(100% - 300px - 50px);
328
  float: left;
329
  margin-bottom: 10px;
330
  }
@@ -387,7 +387,7 @@ table.widefat.currency_lang_table {
387
  width: 100%;
388
  li {
389
  float: left;
390
- margin: 0 8px 0 0;
391
  padding: 2px 8px;
392
  border: 1px solid #DFDFDF;
393
  border-radius: 2px;
@@ -471,9 +471,12 @@ input[name="wcml_curr_template"] {
471
  margin-bottom: $margin-xs*.5;
472
  }
473
  }
474
- &.wcml-plugins-status-list li,
475
  &.wcml-tax-translation-list li {
476
- margin-bottom: $margin-sm;
 
 
 
 
477
  }
478
  [class*="otgs-ico"]:not(.otgs-ico-help) {
479
  margin-left: -25px;
72
  }
73
  }
74
 
75
+ .wcml-section-content .wcml-section-content-inner:not(:last-child) {
76
  margin: 0 0 20px 0;
77
  padding: 0 0 10px 0;
78
  border-bottom: 1px solid #ededed;
 
 
79
  }
80
 
81
  .wcml-section-header {
82
+ width: 310px;
83
  float: left;
84
  h3 {
85
  font-weight: normal;
93
 
94
  .wcml-section-content {
95
  float: left;
96
+ width: 680px;
97
  margin-left: 30px;
98
  }
99
 
146
  }
147
  input {
148
  margin: 0 !important;
149
+ width: 75px;
150
  }
151
  .wcml-co-set-rate {
152
  display: inline-block;
153
  padding: 4px $margin-sm $margin-xs $margin-sm;
154
+ max-width: 265px;
155
  }
156
  small {
157
  display: block;
158
+ margin-top: 5px;
159
  }
160
  }
161
  .wcml-co-help-link {
183
 
184
  table.widefat.currency_table {
185
  float: left;
186
+ width: 320px;
187
  border-right: none;
188
 
189
  td.wcml-col-currency,
195
 
196
  td.wcml-col-currency {
197
  .truncate {
198
+ max-width: 120px;
199
  display: block;
200
  }
201
  small {
324
  }
325
 
326
  .currency_wrap {
327
+ width: calc(100% - 320px - 50px);
328
  float: left;
329
  margin-bottom: 10px;
330
  }
387
  width: 100%;
388
  li {
389
  float: left;
390
+ margin: 2px 4px 2px 0;
391
  padding: 2px 8px;
392
  border: 1px solid #DFDFDF;
393
  border-radius: 2px;
471
  margin-bottom: $margin-xs*.5;
472
  }
473
  }
 
474
  &.wcml-tax-translation-list li {
475
+ margin-bottom: 5px;
476
+ line-height: 26px;
477
+ }
478
+ &.wcml-plugins-status-list li{
479
+ margin-bottom: 10px;
480
  }
481
  [class*="otgs-ico"]:not(.otgs-ico-help) {
482
  margin-left: -25px;
templates/multi-currency/currency-switcher-options.twig CHANGED
@@ -1,5 +1,5 @@
1
- <div class="wcml-section">
2
- <div id="currency-switcher" {% if multi_currency_on is empty %}style="display:none"{% endif %}>
3
 
4
  <div class="wcml-section-header">
5
  <h3>{{ currency_switcher.headers.main }}</h3>
@@ -7,7 +7,7 @@
7
 
8
  <div class="wcml-section-content">
9
 
10
- <div id="wcml_curr_sel_preview_wrap" class="wcml-section-content-inner aligncenter">
11
  <p><strong>{{ currency_switcher.preview_text}}</strong></p>
12
  <input type="hidden" id="wcml_currencies_switcher_preview_nonce" value="{{ currency_switcher.preview_nonce }}"/>
13
  <div id="wcml_curr_sel_preview" class="wcml-currency-preview">
@@ -80,5 +80,5 @@
80
  </div>
81
 
82
  </div>
83
- </div>
84
  </div>
1
+ <div class="wcml-section" id="currency-switcher" {% if multi_currency_on is empty %}style="display:none"{% endif %}>
2
+
3
 
4
  <div class="wcml-section-header">
5
  <h3>{{ currency_switcher.headers.main }}</h3>
7
 
8
  <div class="wcml-section-content">
9
 
10
+ <div id="wcml_curr_sel_preview_wrap" class="wcml-section-content-inner text-center">
11
  <p><strong>{{ currency_switcher.preview_text}}</strong></p>
12
  <input type="hidden" id="wcml_currencies_switcher_preview_nonce" value="{{ currency_switcher.preview_nonce }}"/>
13
  <div id="wcml_curr_sel_preview" class="wcml-currency-preview">
80
  </div>
81
 
82
  </div>
83
+
84
  </div>
templates/multi-currency/custom-currency-options.twig CHANGED
@@ -21,16 +21,17 @@
21
 
22
  <div class="wpml-form-row wcml-co-exchange-rate">
23
  <label for="wcml_currency_options_rate_{{ args.currency_code }}">{{ form.rate.label }}</label>
24
- <small class="alignright wcml-co-help-link"><a href="{{ currency_converter_url|format(args.default_currency, args.currency_code) }}" title="{{ currency_converter_title }}" target="_blank">{{ currency_converter_label }}</a></small>
25
  <div class="wcml-co-set-rate">
26
- 1 {{ args.default_currency }} = <input name="currency_options[rate]" size="5" type="number" class="ext_rate"
 
27
  step="0.01" value="{{ args.currency.rate }}" data-message="{{ form.rate.only_numeric }}"
28
- id="wcml_currency_options_rate_{{ args.currency_code }}" />
 
29
  <span class="this-currency">{{ current_currency }}</span>
30
 
31
  {% if args.currency.updated %}
32
  <small>
33
- <i>{{ form.rate.set_on }}</i>
34
  </small>
35
  {% endif %}
36
  </div>
21
 
22
  <div class="wpml-form-row wcml-co-exchange-rate">
23
  <label for="wcml_currency_options_rate_{{ args.currency_code }}">{{ form.rate.label }}</label>
 
24
  <div class="wcml-co-set-rate">
25
+ 1 {{ args.default_currency }} = <input name="currency_options[rate]" size="5" type="number"
26
+ class="ext_rate{% if automatic_rates %} wcml-tip{% endif %}"
27
  step="0.01" value="{{ args.currency.rate }}" data-message="{{ form.rate.only_numeric }}"
28
+ id="wcml_currency_options_rate_{{ args.currency_code }}"
29
+ {% if automatic_rates %}readonly="readonly" data-tip="{{ automatic_rates_tip }}"{% endif %}/>
30
  <span class="this-currency">{{ current_currency }}</span>
31
 
32
  {% if args.currency.updated %}
33
  <small>
34
+ {{ form.rate.set_on }} <i>{{ form.rate.previous }}</i>
35
  </small>
36
  {% endif %}
37
  </div>
templates/multi-currency/exchange-rates.twig ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="wcml-section" id="online-exchange-rates" {% if multi_currency_on is empty %}style="display:none"{% endif %}>
2
+
3
+ <div class="wcml-section-header">
4
+ <h3>{{ exchange_rates.strings.header }}</h3>
5
+ </div>
6
+
7
+ <div class="wcml-section-content" id="online-exchange-rates-no-currencies" {% if exchange_rates.secondary_currencies %} style="display:none"{% endif %}>
8
+ <p><i>{{ exchange_rates.strings.no_currencies }}</i></p>
9
+ </div>
10
+ <div class="wcml-section-content" {% if exchange_rates.secondary_currencies is empty %} style="display:none"{% endif %}>
11
+ <p>
12
+ <input type="checkbox" id="exchange-rates-automatic" name="exchange-rates-automatic" value="1"
13
+ {% if exchange_rates.settings.automatic == 1 %}checked="checked"{% endif %} />
14
+ <label for="exchange-rates-automatic">{{ exchange_rates.strings.enable_automatic }}</label>
15
+ </p>
16
+
17
+ <div id="exchange-rates-online-wrap"
18
+ class="exchange-rates-online-wrap"{% if exchange_rates.settings.automatic == 0 %} style="display: none;"{% endif %} >
19
+
20
+ <div class="wcml-section-content-inner">
21
+ <p id="update-rates-time">{{ exchange_rates.strings.updated_time|raw }}</p>
22
+
23
+ <p>
24
+ <input type="button" id="update-rates-manually" class="button-secondary"
25
+ value="{{ exchange_rates.strings.update }}" />
26
+ <i class="otgs-ico-help wcml-tip" data-tip="{{ exchange_rates.strings.update_tip }}" style="display: none"></i>
27
+ <span id="update-rates-spinner" class="spinner" style="float:none;"></span>
28
+ <input type="hidden" id="update-exchange-rates-nonce" value="{{ exchange_rates.strings.nonce }}"/>
29
+ </p>
30
+
31
+ <p class="notice inline notice-success" id="exchange-rates-success"
32
+ style="display:none">{{ exchange_rates.strings.updated_success }}</p>
33
+ <p class="notice inline notice-error" id="exchange-rates-error" style="display:none"></p>
34
+ </div>
35
+
36
+ <div class="wcml-section-content-inner">
37
+ <h4>{{ exchange_rates.strings.services_label }}</h4>
38
+ <ul class="exchange-rates-sources">
39
+
40
+ {% for id, service in exchange_rates.services %}
41
+ <li>
42
+ <input type="radio" id="service-{{ id }}" name="exchange-rates-service" value="{{ id }}"
43
+ {% if exchange_rates.settings.service == id %}checked="checked"{% endif %} />
44
+ <label for="service-{{ id }}">
45
+ {{ service.name }}
46
+ </label>
47
+ <a href="{{ service.url }}" title="{{ exchange_rates.strings.visit_website }}" class="exchange-rate-service-website no-ico" target="_blank">
48
+ <span class="dashicons dashicons-external"></span>
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" id="service-error-{{ id }}" {% if service.last_error == false %}style="display:none"{% endif %}>
62
+ {% if service.last_error %}
63
+ {{service.last_error.text}} <i>({{service.last_error.time}})</i>
64
+ {% endif %}
65
+ </p>
66
+
67
+ </div>
68
+ </li>
69
+ {% endfor %}
70
+ </ul>
71
+ </div>
72
+
73
+ <div class="wcml-section-content-inner">
74
+ <h4>{{ exchange_rates.strings.lifting_label }}</h4>
75
+ <p>{{ exchange_rates.strings.lifting_details1 }}</p>
76
+ <input type="number" name="lifting_charge" value="{{ settings.lifting_charge }}" step="any" style="width:64px" /> %
77
+ <p><i>{{ exchange_rates.strings.lifting_details2|format( exchange_rates.services[exchange_rates.settings.service].name ) }}</i></p>
78
+ </div>
79
+
80
+ <div class="wcml-section-content-inner">
81
+
82
+ <h4>{{ exchange_rates.strings.frequency }}</h4>
83
+
84
+ <ul>
85
+ <li>
86
+ <input type="radio" id="update-frequency-daily" name="update-schedule" value="daily"
87
+ {% if exchange_rates.settings.schedule == 'daily' %}checked="checked"{% endif %}/>
88
+ <label for="update-frequency-daily">{{ exchange_rates.strings.daily }}</label>
89
+ </li>
90
+
91
+ <li>
92
+ <input type="radio" id="update-frequency-weekly" name="update-schedule" value="weekly"
93
+ {% if exchange_rates.settings.schedule == 'weekly' %}checked="checked"{% endif %} />
94
+ <label for="update-frequency-weekly">{{ exchange_rates.strings.weekly }}</label>
95
+ <select name="update-weekly-day"
96
+ {% if exchange_rates.settings.schedule != 'weekly' %}disabled{% endif %}>
97
+ {% for i in 0..6 %}
98
+ <option value="{{ i }}"{% if exchange_rates.settings.week_day == i %} selected="selected"{% endif %}>{{ get_weekday(i) }}</option>
99
+ {% endfor %}
100
+ </select>
101
+ </li>
102
+
103
+ <li>
104
+ <input type="radio" id="update-frequency-monthly" name="update-schedule" value="monthly"
105
+ {% if exchange_rates.settings.schedule == 'monthly' %}checked="checked"{% endif %} />
106
+ <label for="update-frequency-monthly">{{ exchange_rates.strings.monthly }}</label>
107
+ <select name="update-monthly-day"
108
+ {% if exchange_rates.settings.schedule != 'monthly' %}disabled{% endif %}>
109
+ {% for i in 1..31 %}
110
+ <option value="{{ i }}"{% if exchange_rates.settings.month_day == i %} selected="selected"{% endif %}>{{ i }}{% if i == 1 %}st{% elseif i == 2 %}nd{% elseif i == 2 %}rd{% else %}th{% endif %}</option>
111
+ {% endfor %}
112
+ </select>
113
+ </li>
114
+
115
+ <li>
116
+ <input type="radio" id="update-frequency-manual" name="update-schedule" value="manual"
117
+ {% if exchange_rates.settings.schedule == 'manual' %}checked="checked"{% endif %} />
118
+ <label for="update-frequency-manual">{{ exchange_rates.strings.manually }}</label>
119
+ </li>
120
+ </ul>
121
+ </div>
122
+ </div>
123
+ </div>
124
+ </div>
templates/multi-currency/multi-currency.twig CHANGED
@@ -83,7 +83,9 @@
83
  <span class="truncate">{{ attribute(wc_currencies, code)|raw }}</span>
84
  <small>{{ attribute( currencies_positions, code )|raw }}</small>
85
  </td>
86
- <td class="wcml-col-rate">{{ get_rate(wc_currency, currency.rate, code) }}</td>
 
 
87
 
88
  <td class="wcml-col-edit">
89
  <a href="#" title="{{ strings.currencies_table.edit }}" class="edit_currency js-wcml-dialog-trigger"
@@ -241,6 +243,8 @@
241
 
242
  </div>
243
 
 
 
244
  {% include 'currency-switcher-options.twig' %}
245
 
246
  <input type="hidden" id="wcml_warn_message" value="{{ form.navigate_warn }}" />
83
  <span class="truncate">{{ attribute(wc_currencies, code)|raw }}</span>
84
  <small>{{ attribute( currencies_positions, code )|raw }}</small>
85
  </td>
86
+ <td class="wcml-col-rate">
87
+ 1 {{ wc_currency }} = <span class="rate">{{ currency.rate }}</span> {{ code }}
88
+ </td>
89
 
90
  <td class="wcml-col-edit">
91
  <a href="#" title="{{ strings.currencies_table.edit }}" class="edit_currency js-wcml-dialog-trigger"
243
 
244
  </div>
245
 
246
+ {% include 'exchange-rates.twig' with exchange_rates %}
247
+
248
  {% include 'currency-switcher-options.twig' %}
249
 
250
  <input type="hidden" id="wcml_warn_message" value="{{ form.navigate_warn }}" />
templates/pointer-ui.twig ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="wcml-pointer-block" data-selector="{{ selector }}" data-insert-method="{{ insert_method }}" style="display:none;">
2
+ <a id="wcml-pointer-target-{{ pointer }}" href="javascript:void(0)" class="otgs-ico-wpml wcml-pointer-link"
3
+ data-wcml-open-pointer="wcml-pointer-{{ pointer }}" title="{{ description.trnsl_title|e }}">{{ description.trnsl_title|e }}</a>
4
+
5
+ <div id="wcml-pointer-{{ pointer }}" style="display:none;">
6
+ <div class="wcml-pointer-inner">
7
+ <div class="wcml-message-content wcml-table-cell">
8
+ <p class="wcml-information-paragraph">
9
+ {{ description.content|raw }}
10
+ </p>
11
+ <p class="wcml-information-link">
12
+ <a class="wcml-external-link" href="{{ description.doc_link }}" target="_blank">
13
+ {{ description.doc_link_text }}
14
+ </a>
15
+ </p>
16
+ </div>
17
+ </div>
18
+ </div>
19
+ </div>
templates/removed-cart-items.twig ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% if products %}
2
+ <h2 class="widget-title">{{ title }}</h2>
3
+ <ul class="wcml_removed_cart_items">
4
+ {% for product in products %}
5
+ <li rel="{{ product.id }}" >
6
+ <a href="{{ product.url|raw }}">
7
+ {{ product.title|raw }}
8
+ </a>
9
+ </li>
10
+ {% endfor %}
11
+ </ul>
12
+ <a href="" class="wcml_removed_cart_items_clear">{{ clear }}</a>
13
+ <input type="hidden" id="wcml_clear_removed_items_nonce" value="{{ nonce|raw }}" />
14
+ {% endif %}
templates/settings-ui.twig CHANGED
@@ -84,6 +84,56 @@
84
 
85
  </div> <!-- .wcml-section -->
86
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  {{ form.nonce|raw }}
88
  <p class="wpml-margin-top-sm">
89
  <input type='submit' name="wcml_save_settings" value='{{ form.save_label }}' class='button-primary'/>
84
 
85
  </div> <!-- .wcml-section -->
86
 
87
+
88
+ <div class="wcml-section">
89
+ <div class="wcml-section-header">
90
+ <h3>
91
+ {{ form.cart_sync.heading }}
92
+ <i class="otgs-ico-help wcml-tip" data-tip="{{ form.cart_sync.tip }}"></i>
93
+ </h3>
94
+ </div>
95
+ <div class="wcml-section-content">
96
+ <div class="wcml-section-content-inner">
97
+ <h4>
98
+ {{ form.cart_sync.lang_switch.heading }}
99
+ </h4>
100
+ <ul>
101
+ <li>
102
+ <input type="radio" name="cart_sync_lang" value="{{ wcml_cart_sync }}"
103
+ {% if form.cart_sync.lang_switch.value == wcml_cart_sync %} checked="checked"{% endif %} id="wcml_cart_sync_lang_sync" />
104
+ <label for="wcml_cart_sync_lang_sync">{{ form.cart_sync.lang_switch.sync_label|raw }}</label>
105
+ </li>
106
+ <li>
107
+ <input type="radio" name="cart_sync_lang" value="{{ wcml_cart_clear }}"
108
+ {% if form.cart_sync.lang_switch.value == wcml_cart_clear %} checked="checked"{% endif %} id="wcml_cart_sync_lang_clear" />
109
+ <label for="wcml_cart_sync_lang_clear">{{ form.cart_sync.lang_switch.clear_label|raw }}</label>
110
+ </li>
111
+ </ul>
112
+ </div>
113
+ <div class="wcml-section-content-inner">
114
+ <h4>
115
+ {{ form.cart_sync.currency_switch.heading }}
116
+ </h4>
117
+ <ul>
118
+ <li>
119
+ <input type="radio" name="cart_sync_currencies" value="{{ wcml_cart_sync }}"
120
+ {% if form.cart_sync.currency_switch.value == wcml_cart_sync %} checked="checked"{% endif %} id="wcml_cart_sync_curr_sync" />
121
+ <label for="wcml_cart_sync_curr_sync">{{ form.cart_sync.currency_switch.sync_label|raw }}</label>
122
+ </li>
123
+ <li>
124
+ <input type="radio" name="cart_sync_currencies" value="{{ wcml_cart_clear }}"
125
+ {% if form.cart_sync.currency_switch.value == wcml_cart_clear %} checked="checked"{% endif %} id="wcml_cart_sync_curr_clear" />
126
+ <label for="wcml_cart_sync_curr_clear">{{ form.cart_sync.currency_switch.clear_label|raw }}</label>
127
+ </li>
128
+ </ul>
129
+ <p>
130
+ {{ form.cart_sync.doc_link|raw }}
131
+ </p>
132
+ </div>
133
+ </div> <!-- .wcml-section-content -->
134
+
135
+ </div> <!-- .wcml-section -->
136
+
137
  {{ form.nonce|raw }}
138
  <p class="wpml-margin-top-sm">
139
  <input type='submit' name="wcml_save_settings" value='{{ form.save_label }}' class='button-primary'/>
templates/status/conf-warn.twig CHANGED
@@ -3,7 +3,6 @@
3
  <div class="wcml-section-header">
4
  <h3>
5
  {{ strings.conf }}
6
- <i class="otgs-ico-help wcml-tip" data-tip="{{ strings.report }}"></i>
7
  </h3>
8
  </div>
9
  <div class="wcml-section-content">
3
  <div class="wcml-section-header">
4
  <h3>
5
  {{ strings.conf }}
 
6
  </h3>
7
  </div>
8
  <div class="wcml-section-content">
templates/status/taxonomies.twig CHANGED
@@ -6,21 +6,15 @@
6
  </h3>
7
  </div>
8
  <div class="wcml-section-content js-tax-translation">
9
- <input type="hidden" id="wcml_ingore_taxonomy_translation_nonce" value="{{ nonces.ignore_tax }}"/>
10
  <ul class="wcml-status-list wcml-tax-translation-list">
11
  {% set no_tax_to_update = true %}
12
- {% for taxonomy in taxonomies if ( taxonomy.tax != 'product_type' and taxonomy.untranslated != 0 ) %}
13
  {% set no_tax_to_update = false %}
14
  <li class="js-tax-translation-{{ taxonomy.tax }}">
15
  {% if taxonomy.untranslated %}
16
  {% if taxonomy.fully_trans %}
17
  <i class="otgs-ico-ok"></i>
18
  {{ strings.not_req_trnsl|format( taxonomy.name ) }}
19
- <small class="actions">
20
- <a class="unignore-{{ taxonomy.tax }}" href="#unignore-{{ taxonomy.tax }}" title="{{ strings.req_trnsl|e }}">
21
- {{ strings.incl_trnsl }}
22
- </a>
23
- </small>
24
  {% else %}
25
  <i class="otgs-ico-warning"></i>
26
  {% if( taxonomy.untranslated == 1) %}
@@ -28,14 +22,9 @@
28
  {% else %}
29
  {{ strings.miss_trnsl_more|format( taxonomy.untranslated, taxonomy.name ) }}
30
  {% endif %}
31
- <a class="button-secondary" href="{{ taxonomy.url }}">
32
  {{ strings.trnsl|format( taxonomy.name ) }}
33
  </a>
34
- <small class="actions">
35
- <a class="ignore-{{ taxonomy.tax }}" href="#ignore-{{ taxonomy.tax }}" title="{{ strings.doesnot_req_trnsl }}">
36
- {{ strings.exclude }}
37
- </a>
38
- </small>
39
  {% endif %}
40
  {% else %}
41
  <i class="otgs-ico-ok"></i>
@@ -50,5 +39,6 @@
50
  </li>
51
  {% endif %}
52
  </ul>
 
53
  </div>
54
  </div>
6
  </h3>
7
  </div>
8
  <div class="wcml-section-content js-tax-translation">
 
9
  <ul class="wcml-status-list wcml-tax-translation-list">
10
  {% set no_tax_to_update = true %}
11
+ {% for taxonomy in taxonomies %}
12
  {% set no_tax_to_update = false %}
13
  <li class="js-tax-translation-{{ taxonomy.tax }}">
14
  {% if taxonomy.untranslated %}
15
  {% if taxonomy.fully_trans %}
16
  <i class="otgs-ico-ok"></i>
17
  {{ strings.not_req_trnsl|format( taxonomy.name ) }}
 
 
 
 
 
18
  {% else %}
19
  <i class="otgs-ico-warning"></i>
20
  {% if( taxonomy.untranslated == 1) %}
22
  {% else %}
23
  {{ strings.miss_trnsl_more|format( taxonomy.untranslated, taxonomy.name ) }}
24
  {% endif %}
25
+ <a class="button button-secondary button-small" href="{{ taxonomy.url }}">
26
  {{ strings.trnsl|format( taxonomy.name ) }}
27
  </a>
 
 
 
 
 
28
  {% endif %}
29
  {% else %}
30
  <i class="otgs-ico-ok"></i>
39
  </li>
40
  {% endif %}
41
  </ul>
42
+ <span>{{ strings.conf_warning|raw }}</span>
43
  </div>
44
  </div>
vendor/autoload.php CHANGED
@@ -2,6 +2,6 @@
2
 
3
  // autoload.php @generated by Composer
4
 
5
- require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
- return ComposerAutoloaderInita047ff959ab47e6831cb2bbccf3ea361::getLoader();
2
 
3
  // autoload.php @generated by Composer
4
 
5
+ require_once __DIR__ . '/composer' . '/autoload_real.php';
6
 
7
+ return ComposerAutoloaderInitc525bb0b8d85f267088abc6242e03a75::getLoader();
vendor/autoload_52.php CHANGED
@@ -4,4 +4,4 @@
4
 
5
  require_once dirname(__FILE__) . '/composer'.'/autoload_real_52.php';
6
 
7
- return ComposerAutoloaderInit4f613025b1ca04c0979df243c5eb8eb7::getLoader();
4
 
5
  require_once dirname(__FILE__) . '/composer'.'/autoload_real_52.php';
6
 
7
+ return ComposerAutoloaderInitdbec6276ad1c64a65a0dc3fc977a2382::getLoader();
vendor/composer/ClassLoader.php CHANGED
@@ -53,8 +53,8 @@ class ClassLoader
53
 
54
  private $useIncludePath = false;
55
  private $classMap = array();
 
56
  private $classMapAuthoritative = false;
57
- private $missingClasses = array();
58
 
59
  public function getPrefixes()
60
  {
@@ -313,24 +313,29 @@ class ClassLoader
313
  */
314
  public function findFile($class)
315
  {
 
 
 
 
 
316
  // class map lookup
317
  if (isset($this->classMap[$class])) {
318
  return $this->classMap[$class];
319
  }
320
- if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
321
  return false;
322
  }
323
 
324
  $file = $this->findFileWithExtension($class, '.php');
325
 
326
  // Search for Hack files if we are running on HHVM
327
- if (false === $file && defined('HHVM_VERSION')) {
328
  $file = $this->findFileWithExtension($class, '.hh');
329
  }
330
 
331
- if (false === $file) {
332
  // Remember that this class does not exist.
333
- $this->missingClasses[$class] = true;
334
  }
335
 
336
  return $file;
@@ -394,8 +399,6 @@ class ClassLoader
394
  if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
395
  return $file;
396
  }
397
-
398
- return false;
399
  }
400
  }
401
 
53
 
54
  private $useIncludePath = false;
55
  private $classMap = array();
56
+
57
  private $classMapAuthoritative = false;
 
58
 
59
  public function getPrefixes()
60
  {
313
  */
314
  public function findFile($class)
315
  {
316
+ // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731
317
+ if ('\\' == $class[0]) {
318
+ $class = substr($class, 1);
319
+ }
320
+
321
  // class map lookup
322
  if (isset($this->classMap[$class])) {
323
  return $this->classMap[$class];
324
  }
325
+ if ($this->classMapAuthoritative) {
326
  return false;
327
  }
328
 
329
  $file = $this->findFileWithExtension($class, '.php');
330
 
331
  // Search for Hack files if we are running on HHVM
332
+ if ($file === null && defined('HHVM_VERSION')) {
333
  $file = $this->findFileWithExtension($class, '.hh');
334
  }
335
 
336
+ if ($file === null) {
337
  // Remember that this class does not exist.
338
+ return $this->classMap[$class] = false;
339
  }
340
 
341
  return $file;
399
  if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
400
  return $file;
401
  }
 
 
402
  }
403
  }
404
 
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_Currency_Selector' => $baseDir . '/inc/currencies/class-wcml-admin-currency-selector.php',
11
  'WCML_Admin_Menus' => $baseDir . '/inc/admin-menus/class-wcml-admin-menus.php',
@@ -19,6 +20,8 @@ return array(
19
  'WCML_Bulk_Stock_Management' => $baseDir . '/compatibility/class-wcml-bulk-stock-management.php',
20
  'WCML_Capabilities' => $baseDir . '/inc/class-wcml-capabilities.php',
21
  'WCML_Cart' => $baseDir . '/inc/class-wcml-cart.php',
 
 
22
  'WCML_Checkout_Addons' => $baseDir . '/compatibility/class-wcml-checkout-addons.php',
23
  'WCML_Checkout_Field_Editor' => $baseDir . '/compatibility/class-wcml-checkout-field-editor.php',
24
  'WCML_Compatibility' => $baseDir . '/inc/class-wcml-compatibility.php',
@@ -41,6 +44,12 @@ return array(
41
  'WCML_Editor_UI_Product_Job' => $baseDir . '/inc/translation-editor/class-wcml-editor-ui-product-job.php',
42
  'WCML_Emails' => $baseDir . '/inc/class-wcml-emails.php',
43
  'WCML_Endpoints' => $baseDir . '/inc/class-wcml-endpoints.php',
 
 
 
 
 
 
44
  'WCML_Extra_Product_Options' => $baseDir . '/compatibility/class-wcml-extra-product-options.php',
45
  'WCML_Fix_Copied_Custom_Fields_WPML353' => $baseDir . '/inc/class-wcml-fix-copied-custom-fields-wpml353.php',
46
  'WCML_Flatsome' => $baseDir . '/compatibility/class-wcml-flatsome.php',
@@ -70,12 +79,14 @@ return array(
70
  'WCML_Per_Product_Shipping' => $baseDir . '/compatibility/class-wcml-per-product-shipping.php',
71
  'WCML_Pip' => $baseDir . '/compatibility/class-wcml-pip.php',
72
  'WCML_Plugins_Wrap' => $baseDir . '/inc/template-classes/class-wcml-plugins-wrap.php',
 
73
  'WCML_Pointers' => $baseDir . '/inc/admin-menus/class-wcml-pointers.php',
74
  'WCML_Product_Addons' => $baseDir . '/compatibility/class-wcml-product-addons.php',
75
  'WCML_Product_Bundles' => $baseDir . '/compatibility/class-wcml-product-bundles.php',
76
  'WCML_Products' => $baseDir . '/inc/class-wcml-products.php',
77
  'WCML_Products_Screen_Options' => $baseDir . '/inc/class-wcml-products-screen-options.php',
78
  'WCML_Products_UI' => $baseDir . '/inc/template-classes/class-wcml-products-ui.php',
 
79
  'WCML_Reports' => $baseDir . '/inc/class-wcml-reports.php',
80
  'WCML_Requests' => $baseDir . '/inc/class-wcml-requests.php',
81
  'WCML_Resources' => $baseDir . '/inc/class-wcml-resources.php',
@@ -119,6 +130,7 @@ return array(
119
  'WCML_WC_Strings' => $baseDir . '/inc/class-wcml-wc-strings.php',
120
  'WCML_WC_Subscriptions' => $baseDir . '/compatibility/class-wcml-wc-subscriptions.php',
121
  'WCML_WPSEO' => $baseDir . '/compatibility/class-wcml-wpseo.php',
 
122
  'WCML_WooCommerce_Rest_API_Support' => $baseDir . '/inc/class-wcml-woocommerce-rest-api-support.php',
123
  'WCML_gravityforms' => $baseDir . '/compatibility/class-wcml-gravityforms.php',
124
  'WCML_sensei' => $baseDir . '/compatibility/class-wcml-sensei.php',
6
  $baseDir = dirname($vendorDir);
7
 
8
  return array(
9
+ 'Deprecated_WC_Functions' => $baseDir . '/inc/deprecated-WC-functions.php',
10
  'WCML_Accommodation_Bookings' => $baseDir . '/compatibility/class-wcml-accommodation-bookings.php',
11
  'WCML_Admin_Currency_Selector' => $baseDir . '/inc/currencies/class-wcml-admin-currency-selector.php',
12
  'WCML_Admin_Menus' => $baseDir . '/inc/admin-menus/class-wcml-admin-menus.php',
20
  'WCML_Bulk_Stock_Management' => $baseDir . '/compatibility/class-wcml-bulk-stock-management.php',
21
  'WCML_Capabilities' => $baseDir . '/inc/class-wcml-capabilities.php',
22
  'WCML_Cart' => $baseDir . '/inc/class-wcml-cart.php',
23
+ 'WCML_Cart_Removed_Items_Widget' => $baseDir . '/inc/class-wcml-cart-removed-items-widget.php',
24
+ 'WCML_Cart_Switch_Lang_Functions' => $baseDir . '/inc/wcml-cart-switch-lang-functions.php',
25
  'WCML_Checkout_Addons' => $baseDir . '/compatibility/class-wcml-checkout-addons.php',
26
  'WCML_Checkout_Field_Editor' => $baseDir . '/compatibility/class-wcml-checkout-field-editor.php',
27
  'WCML_Compatibility' => $baseDir . '/inc/class-wcml-compatibility.php',
44
  'WCML_Editor_UI_Product_Job' => $baseDir . '/inc/translation-editor/class-wcml-editor-ui-product-job.php',
45
  'WCML_Emails' => $baseDir . '/inc/class-wcml-emails.php',
46
  'WCML_Endpoints' => $baseDir . '/inc/class-wcml-endpoints.php',
47
+ 'WCML_Exchange_Rate_Service' => $baseDir . '/inc/abstracts/class-wcml-exchange-rate-service.php',
48
+ 'WCML_Exchange_Rates' => $baseDir . '/inc/currencies/class-wcml-exchange-rates.php',
49
+ 'WCML_Exchange_Rates_Currencylayer' => $baseDir . '/inc/currencies/exchange-rate-services/class-wcml-exchange-rates-currencylayer.php',
50
+ 'WCML_Exchange_Rates_Fixierio' => $baseDir . '/inc/currencies/exchange-rate-services/class-wcml-exchange-rates-fixierio.php',
51
+ 'WCML_Exchange_Rates_UI' => $baseDir . '/inc/template-classes/multi-currency/class-wcml-exchange-rates-ui.php',
52
+ 'WCML_Exchange_Rates_YahooFinance' => $baseDir . '/inc/currencies/exchange-rate-services/class-wcml-exchange-rates-yahoo-finance.php',
53
  'WCML_Extra_Product_Options' => $baseDir . '/compatibility/class-wcml-extra-product-options.php',
54
  'WCML_Fix_Copied_Custom_Fields_WPML353' => $baseDir . '/inc/class-wcml-fix-copied-custom-fields-wpml353.php',
55
  'WCML_Flatsome' => $baseDir . '/compatibility/class-wcml-flatsome.php',
79
  'WCML_Per_Product_Shipping' => $baseDir . '/compatibility/class-wcml-per-product-shipping.php',
80
  'WCML_Pip' => $baseDir . '/compatibility/class-wcml-pip.php',
81
  'WCML_Plugins_Wrap' => $baseDir . '/inc/template-classes/class-wcml-plugins-wrap.php',
82
+ 'WCML_Pointer_UI' => $baseDir . '/inc/template-classes/class-wcml-pointer-ui.php',
83
  'WCML_Pointers' => $baseDir . '/inc/admin-menus/class-wcml-pointers.php',
84
  'WCML_Product_Addons' => $baseDir . '/compatibility/class-wcml-product-addons.php',
85
  'WCML_Product_Bundles' => $baseDir . '/compatibility/class-wcml-product-bundles.php',
86
  'WCML_Products' => $baseDir . '/inc/class-wcml-products.php',
87
  'WCML_Products_Screen_Options' => $baseDir . '/inc/class-wcml-products-screen-options.php',
88
  'WCML_Products_UI' => $baseDir . '/inc/template-classes/class-wcml-products-ui.php',
89
+ 'WCML_Removed_Cart_Items_UI' => $baseDir . '/inc/template-classes/class-wcml-removed-cart-items-ui.php',
90
  'WCML_Reports' => $baseDir . '/inc/class-wcml-reports.php',
91
  'WCML_Requests' => $baseDir . '/inc/class-wcml-requests.php',
92
  'WCML_Resources' => $baseDir . '/inc/class-wcml-resources.php',
130
  'WCML_WC_Strings' => $baseDir . '/inc/class-wcml-wc-strings.php',
131
  'WCML_WC_Subscriptions' => $baseDir . '/compatibility/class-wcml-wc-subscriptions.php',
132
  'WCML_WPSEO' => $baseDir . '/compatibility/class-wcml-wpseo.php',
133
+ 'WCML_Widgets' => $baseDir . '/inc/class-wcml-widgets.php',
134
  'WCML_WooCommerce_Rest_API_Support' => $baseDir . '/inc/class-wcml-woocommerce-rest-api-support.php',
135
  'WCML_gravityforms' => $baseDir . '/compatibility/class-wcml-gravityforms.php',
136
  'WCML_sensei' => $baseDir . '/compatibility/class-wcml-sensei.php',
vendor/composer/autoload_real.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
- class ComposerAutoloaderInita047ff959ab47e6831cb2bbccf3ea361
6
  {
7
  private static $loader;
8
 
@@ -19,15 +19,15 @@ class ComposerAutoloaderInita047ff959ab47e6831cb2bbccf3ea361
19
  return self::$loader;
20
  }
21
 
22
- spl_autoload_register(array('ComposerAutoloaderInita047ff959ab47e6831cb2bbccf3ea361', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
- spl_autoload_unregister(array('ComposerAutoloaderInita047ff959ab47e6831cb2bbccf3ea361', 'loadClassLoader'));
25
 
26
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION');
27
  if ($useStaticLoader) {
28
  require_once __DIR__ . '/autoload_static.php';
29
 
30
- call_user_func(\Composer\Autoload\ComposerStaticInita047ff959ab47e6831cb2bbccf3ea361::getInitializer($loader));
31
  } else {
32
  $map = require __DIR__ . '/autoload_namespaces.php';
33
  foreach ($map as $namespace => $path) {
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
+ class ComposerAutoloaderInitc525bb0b8d85f267088abc6242e03a75
6
  {
7
  private static $loader;
8
 
19
  return self::$loader;
20
  }
21
 
22
+ spl_autoload_register(array('ComposerAutoloaderInitc525bb0b8d85f267088abc6242e03a75', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInitc525bb0b8d85f267088abc6242e03a75', 'loadClassLoader'));
25
 
26
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION');
27
  if ($useStaticLoader) {
28
  require_once __DIR__ . '/autoload_static.php';
29
 
30
+ call_user_func(\Composer\Autoload\ComposerStaticInitc525bb0b8d85f267088abc6242e03a75::getInitializer($loader));
31
  } else {
32
  $map = require __DIR__ . '/autoload_namespaces.php';
33
  foreach ($map as $namespace => $path) {
vendor/composer/autoload_real_52.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real_52.php generated by xrstf/composer-php52
4
 
5
- class ComposerAutoloaderInit4f613025b1ca04c0979df243c5eb8eb7 {
6
  private static $loader;
7
 
8
  public static function loadClassLoader($class) {
@@ -19,9 +19,9 @@ class ComposerAutoloaderInit4f613025b1ca04c0979df243c5eb8eb7 {
19
  return self::$loader;
20
  }
21
 
22
- spl_autoload_register(array('ComposerAutoloaderInit4f613025b1ca04c0979df243c5eb8eb7', 'loadClassLoader'), true /*, true */);
23
  self::$loader = $loader = new xrstf_Composer52_ClassLoader();
24
- spl_autoload_unregister(array('ComposerAutoloaderInit4f613025b1ca04c0979df243c5eb8eb7', '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 ComposerAutoloaderInitdbec6276ad1c64a65a0dc3fc977a2382 {
6
  private static $loader;
7
 
8
  public static function loadClassLoader($class) {
19
  return self::$loader;
20
  }
21
 
22
+ spl_autoload_register(array('ComposerAutoloaderInitdbec6276ad1c64a65a0dc3fc977a2382', 'loadClassLoader'), true /*, true */);
23
  self::$loader = $loader = new xrstf_Composer52_ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInitdbec6276ad1c64a65a0dc3fc977a2382', '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 ComposerStaticInita047ff959ab47e6831cb2bbccf3ea361
8
  {
9
  public static $prefixLengthsPsr4 = array (
10
  'C' =>
@@ -31,6 +31,7 @@ class ComposerStaticInita047ff959ab47e6831cb2bbccf3ea361
31
  );
32
 
33
  public static $classMap = array (
 
34
  'WCML_Accommodation_Bookings' => __DIR__ . '/../..' . '/compatibility/class-wcml-accommodation-bookings.php',
35
  'WCML_Admin_Currency_Selector' => __DIR__ . '/../..' . '/inc/currencies/class-wcml-admin-currency-selector.php',
36
  'WCML_Admin_Menus' => __DIR__ . '/../..' . '/inc/admin-menus/class-wcml-admin-menus.php',
@@ -44,6 +45,8 @@ class ComposerStaticInita047ff959ab47e6831cb2bbccf3ea361
44
  'WCML_Bulk_Stock_Management' => __DIR__ . '/../..' . '/compatibility/class-wcml-bulk-stock-management.php',
45
  'WCML_Capabilities' => __DIR__ . '/../..' . '/inc/class-wcml-capabilities.php',
46
  'WCML_Cart' => __DIR__ . '/../..' . '/inc/class-wcml-cart.php',
 
 
47
  'WCML_Checkout_Addons' => __DIR__ . '/../..' . '/compatibility/class-wcml-checkout-addons.php',
48
  'WCML_Checkout_Field_Editor' => __DIR__ . '/../..' . '/compatibility/class-wcml-checkout-field-editor.php',
49
  'WCML_Compatibility' => __DIR__ . '/../..' . '/inc/class-wcml-compatibility.php',
@@ -66,6 +69,12 @@ class ComposerStaticInita047ff959ab47e6831cb2bbccf3ea361
66
  'WCML_Editor_UI_Product_Job' => __DIR__ . '/../..' . '/inc/translation-editor/class-wcml-editor-ui-product-job.php',
67
  'WCML_Emails' => __DIR__ . '/../..' . '/inc/class-wcml-emails.php',
68
  'WCML_Endpoints' => __DIR__ . '/../..' . '/inc/class-wcml-endpoints.php',
 
 
 
 
 
 
69
  'WCML_Extra_Product_Options' => __DIR__ . '/../..' . '/compatibility/class-wcml-extra-product-options.php',
70
  'WCML_Fix_Copied_Custom_Fields_WPML353' => __DIR__ . '/../..' . '/inc/class-wcml-fix-copied-custom-fields-wpml353.php',
71
  'WCML_Flatsome' => __DIR__ . '/../..' . '/compatibility/class-wcml-flatsome.php',
@@ -95,12 +104,14 @@ class ComposerStaticInita047ff959ab47e6831cb2bbccf3ea361
95
  'WCML_Per_Product_Shipping' => __DIR__ . '/../..' . '/compatibility/class-wcml-per-product-shipping.php',
96
  'WCML_Pip' => __DIR__ . '/../..' . '/compatibility/class-wcml-pip.php',
97
  'WCML_Plugins_Wrap' => __DIR__ . '/../..' . '/inc/template-classes/class-wcml-plugins-wrap.php',
 
98
  'WCML_Pointers' => __DIR__ . '/../..' . '/inc/admin-menus/class-wcml-pointers.php',
99
  'WCML_Product_Addons' => __DIR__ . '/../..' . '/compatibility/class-wcml-product-addons.php',
100
  'WCML_Product_Bundles' => __DIR__ . '/../..' . '/compatibility/class-wcml-product-bundles.php',
101
  'WCML_Products' => __DIR__ . '/../..' . '/inc/class-wcml-products.php',
102
  'WCML_Products_Screen_Options' => __DIR__ . '/../..' . '/inc/class-wcml-products-screen-options.php',
103
  'WCML_Products_UI' => __DIR__ . '/../..' . '/inc/template-classes/class-wcml-products-ui.php',
 
104
  'WCML_Reports' => __DIR__ . '/../..' . '/inc/class-wcml-reports.php',
105
  'WCML_Requests' => __DIR__ . '/../..' . '/inc/class-wcml-requests.php',
106
  'WCML_Resources' => __DIR__ . '/../..' . '/inc/class-wcml-resources.php',
@@ -144,6 +155,7 @@ class ComposerStaticInita047ff959ab47e6831cb2bbccf3ea361
144
  'WCML_WC_Strings' => __DIR__ . '/../..' . '/inc/class-wcml-wc-strings.php',
145
  'WCML_WC_Subscriptions' => __DIR__ . '/../..' . '/compatibility/class-wcml-wc-subscriptions.php',
146
  'WCML_WPSEO' => __DIR__ . '/../..' . '/compatibility/class-wcml-wpseo.php',
 
147
  'WCML_WooCommerce_Rest_API_Support' => __DIR__ . '/../..' . '/inc/class-wcml-woocommerce-rest-api-support.php',
148
  'WCML_gravityforms' => __DIR__ . '/../..' . '/compatibility/class-wcml-gravityforms.php',
149
  'WCML_sensei' => __DIR__ . '/../..' . '/compatibility/class-wcml-sensei.php',
@@ -156,10 +168,10 @@ class ComposerStaticInita047ff959ab47e6831cb2bbccf3ea361
156
  public static function getInitializer(ClassLoader $loader)
157
  {
158
  return \Closure::bind(function () use ($loader) {
159
- $loader->prefixLengthsPsr4 = ComposerStaticInita047ff959ab47e6831cb2bbccf3ea361::$prefixLengthsPsr4;
160
- $loader->prefixDirsPsr4 = ComposerStaticInita047ff959ab47e6831cb2bbccf3ea361::$prefixDirsPsr4;
161
- $loader->prefixesPsr0 = ComposerStaticInita047ff959ab47e6831cb2bbccf3ea361::$prefixesPsr0;
162
- $loader->classMap = ComposerStaticInita047ff959ab47e6831cb2bbccf3ea361::$classMap;
163
 
164
  }, null, ClassLoader::class);
165
  }
4
 
5
  namespace Composer\Autoload;
6
 
7
+ class ComposerStaticInitc525bb0b8d85f267088abc6242e03a75
8
  {
9
  public static $prefixLengthsPsr4 = array (
10
  'C' =>
31
  );
32
 
33
  public static $classMap = array (
34
+ 'Deprecated_WC_Functions' => __DIR__ . '/../..' . '/inc/deprecated-WC-functions.php',
35
  'WCML_Accommodation_Bookings' => __DIR__ . '/../..' . '/compatibility/class-wcml-accommodation-bookings.php',
36
  'WCML_Admin_Currency_Selector' => __DIR__ . '/../..' . '/inc/currencies/class-wcml-admin-currency-selector.php',
37
  'WCML_Admin_Menus' => __DIR__ . '/../..' . '/inc/admin-menus/class-wcml-admin-menus.php',
45
  'WCML_Bulk_Stock_Management' => __DIR__ . '/../..' . '/compatibility/class-wcml-bulk-stock-management.php',
46
  'WCML_Capabilities' => __DIR__ . '/../..' . '/inc/class-wcml-capabilities.php',
47
  'WCML_Cart' => __DIR__ . '/../..' . '/inc/class-wcml-cart.php',
48
+ 'WCML_Cart_Removed_Items_Widget' => __DIR__ . '/../..' . '/inc/class-wcml-cart-removed-items-widget.php',
49
+ 'WCML_Cart_Switch_Lang_Functions' => __DIR__ . '/../..' . '/inc/wcml-cart-switch-lang-functions.php',
50
  'WCML_Checkout_Addons' => __DIR__ . '/../..' . '/compatibility/class-wcml-checkout-addons.php',
51
  'WCML_Checkout_Field_Editor' => __DIR__ . '/../..' . '/compatibility/class-wcml-checkout-field-editor.php',
52
  'WCML_Compatibility' => __DIR__ . '/../..' . '/inc/class-wcml-compatibility.php',
69
  'WCML_Editor_UI_Product_Job' => __DIR__ . '/../..' . '/inc/translation-editor/class-wcml-editor-ui-product-job.php',
70
  'WCML_Emails' => __DIR__ . '/../..' . '/inc/class-wcml-emails.php',
71
  'WCML_Endpoints' => __DIR__ . '/../..' . '/inc/class-wcml-endpoints.php',
72
+ 'WCML_Exchange_Rate_Service' => __DIR__ . '/../..' . '/inc/abstracts/class-wcml-exchange-rate-service.php',
73
+ 'WCML_Exchange_Rates' => __DIR__ . '/../..' . '/inc/currencies/class-wcml-exchange-rates.php',
74
+ 'WCML_Exchange_Rates_Currencylayer' => __DIR__ . '/../..' . '/inc/currencies/exchange-rate-services/class-wcml-exchange-rates-currencylayer.php',
75
+ 'WCML_Exchange_Rates_Fixierio' => __DIR__ . '/../..' . '/inc/currencies/exchange-rate-services/class-wcml-exchange-rates-fixierio.php',
76
+ 'WCML_Exchange_Rates_UI' => __DIR__ . '/../..' . '/inc/template-classes/multi-currency/class-wcml-exchange-rates-ui.php',
77
+ 'WCML_Exchange_Rates_YahooFinance' => __DIR__ . '/../..' . '/inc/currencies/exchange-rate-services/class-wcml-exchange-rates-yahoo-finance.php',
78
  'WCML_Extra_Product_Options' => __DIR__ . '/../..' . '/compatibility/class-wcml-extra-product-options.php',
79
  'WCML_Fix_Copied_Custom_Fields_WPML353' => __DIR__ . '/../..' . '/inc/class-wcml-fix-copied-custom-fields-wpml353.php',
80
  'WCML_Flatsome' => __DIR__ . '/../..' . '/compatibility/class-wcml-flatsome.php',
104
  'WCML_Per_Product_Shipping' => __DIR__ . '/../..' . '/compatibility/class-wcml-per-product-shipping.php',
105
  'WCML_Pip' => __DIR__ . '/../..' . '/compatibility/class-wcml-pip.php',
106
  'WCML_Plugins_Wrap' => __DIR__ . '/../..' . '/inc/template-classes/class-wcml-plugins-wrap.php',
107
+ 'WCML_Pointer_UI' => __DIR__ . '/../..' . '/inc/template-classes/class-wcml-pointer-ui.php',
108
  'WCML_Pointers' => __DIR__ . '/../..' . '/inc/admin-menus/class-wcml-pointers.php',
109
  'WCML_Product_Addons' => __DIR__ . '/../..' . '/compatibility/class-wcml-product-addons.php',
110
  'WCML_Product_Bundles' => __DIR__ . '/../..' . '/compatibility/class-wcml-product-bundles.php',
111
  'WCML_Products' => __DIR__ . '/../..' . '/inc/class-wcml-products.php',
112
  'WCML_Products_Screen_Options' => __DIR__ . '/../..' . '/inc/class-wcml-products-screen-options.php',
113
  'WCML_Products_UI' => __DIR__ . '/../..' . '/inc/template-classes/class-wcml-products-ui.php',
114
+ 'WCML_Removed_Cart_Items_UI' => __DIR__ . '/../..' . '/inc/template-classes/class-wcml-removed-cart-items-ui.php',
115
  'WCML_Reports' => __DIR__ . '/../..' . '/inc/class-wcml-reports.php',
116
  'WCML_Requests' => __DIR__ . '/../..' . '/inc/class-wcml-requests.php',
117
  'WCML_Resources' => __DIR__ . '/../..' . '/inc/class-wcml-resources.php',
155
  'WCML_WC_Strings' => __DIR__ . '/../..' . '/inc/class-wcml-wc-strings.php',
156
  'WCML_WC_Subscriptions' => __DIR__ . '/../..' . '/compatibility/class-wcml-wc-subscriptions.php',
157
  'WCML_WPSEO' => __DIR__ . '/../..' . '/compatibility/class-wcml-wpseo.php',
158
+ 'WCML_Widgets' => __DIR__ . '/../..' . '/inc/class-wcml-widgets.php',
159
  'WCML_WooCommerce_Rest_API_Support' => __DIR__ . '/../..' . '/inc/class-wcml-woocommerce-rest-api-support.php',
160
  'WCML_gravityforms' => __DIR__ . '/../..' . '/compatibility/class-wcml-gravityforms.php',
161
  'WCML_sensei' => __DIR__ . '/../..' . '/compatibility/class-wcml-sensei.php',
168
  public static function getInitializer(ClassLoader $loader)
169
  {
170
  return \Closure::bind(function () use ($loader) {
171
+ $loader->prefixLengthsPsr4 = ComposerStaticInitc525bb0b8d85f267088abc6242e03a75::$prefixLengthsPsr4;
172
+ $loader->prefixDirsPsr4 = ComposerStaticInitc525bb0b8d85f267088abc6242e03a75::$prefixDirsPsr4;
173
+ $loader->prefixesPsr0 = ComposerStaticInitc525bb0b8d85f267088abc6242e03a75::$prefixesPsr0;
174
+ $loader->classMap = ComposerStaticInitc525bb0b8d85f267088abc6242e03a75::$classMap;
175
 
176
  }, null, ClassLoader::class);
177
  }
vendor/composer/installed.json CHANGED
@@ -25,7 +25,7 @@
25
  "composer/composer": "1.0.*@dev",
26
  "phpunit/phpunit": "4.1.*"
27
  },
28
- "time": "2016-08-13T20:53:52+00:00",
29
  "type": "composer-plugin",
30
  "extra": {
31
  "class": "Composer\\Installers\\Plugin",
@@ -115,7 +115,7 @@
115
  "source": {
116
  "type": "git",
117
  "url": "ssh://git@git.onthegosystems.com:10022/installer/installer.git",
118
- "reference": "b94fa43d64695a5b404a363d7f4dd7789df0859b"
119
  },
120
  "require": {
121
  "composer/installers": "~1.0",
@@ -124,7 +124,7 @@
124
  "require-dev": {
125
  "phpunit/phpunit": "~4.5"
126
  },
127
- "time": "2016-11-14T13:48:55+00:00",
128
  "type": "library",
129
  "extra": {
130
  "branch-alias": {
@@ -172,7 +172,7 @@
172
  "reference": "bd41459d5e27df8d33057842b32377c39e97a5a8",
173
  "shasum": ""
174
  },
175
- "time": "2016-04-16T21:52:24+00:00",
176
  "type": "library",
177
  "extra": {
178
  "branch-alias": {
25
  "composer/composer": "1.0.*@dev",
26
  "phpunit/phpunit": "4.1.*"
27
  },
28
+ "time": "2016-08-13 20:53:52",
29
  "type": "composer-plugin",
30
  "extra": {
31
  "class": "Composer\\Installers\\Plugin",
115
  "source": {
116
  "type": "git",
117
  "url": "ssh://git@git.onthegosystems.com:10022/installer/installer.git",
118
+ "reference": "5c03622f8f76baf90ae4cf522116a1df4eb60a6b"
119
  },
120
  "require": {
121
  "composer/installers": "~1.0",
124
  "require-dev": {
125
  "phpunit/phpunit": "~4.5"
126
  },
127
+ "time": "2016-11-30 13:53:07",
128
  "type": "library",
129
  "extra": {
130
  "branch-alias": {
172
  "reference": "bd41459d5e27df8d33057842b32377c39e97a5a8",
173
  "shasum": ""
174
  },
175
+ "time": "2016-04-16 21:52:24",
176
  "type": "library",
177
  "extra": {
178
  "branch-alias": {
vendor/composer/installers/5450262f6ba3420d0675f65877346e3e ADDED
Binary file
vendor/otgs/installer/changelog.txt CHANGED
@@ -1,3 +1,7 @@
 
 
 
 
1
  = 1.7.12 =
2
  * Allow to set the site keys in PHP (as constants)
3
  * Fixed an issue with unregistered sites gets wrong info (or error) when clicking "View version x.y.x details" link
1
+ = 1.7.13 =
2
+ * Added sanitization for some inputs
3
+ * Fixed PHP notice being logged when installing a plugin from the WP plugins directory
4
+
5
  = 1.7.12 =
6
  * Allow to set the site keys in PHP (as constants)
7
  * Fixed an issue with unregistered sites gets wrong info (or error) when clicking "View version x.y.x details" link
vendor/otgs/installer/includes/class-installer-dependencies.php CHANGED
@@ -172,7 +172,7 @@ class Installer_Dependencies{
172
 
173
  if ( isset($_REQUEST['action']) ) {
174
 
175
- $action = isset($_REQUEST['action']) ? $_REQUEST['action'] : '';
176
 
177
  $installer_settings = WP_Installer()->settings;
178
 
@@ -229,7 +229,7 @@ class Installer_Dependencies{
229
 
230
  if( 'upgrade-plugin' == $action || 'update-plugin' == $action ) {
231
 
232
- $plugin = isset($_REQUEST['plugin']) ? trim($_REQUEST['plugin']) : '';
233
 
234
  $wp_plugin_slug = dirname($plugin);
235
 
172
 
173
  if ( isset($_REQUEST['action']) ) {
174
 
175
+ $action = isset($_REQUEST['action']) ? sanitize_text_field ( $_REQUEST['action'] ) : '';
176
 
177
  $installer_settings = WP_Installer()->settings;
178
 
229
 
230
  if( 'upgrade-plugin' == $action || 'update-plugin' == $action ) {
231
 
232
+ $plugin = isset($_REQUEST['plugin']) ? trim( sanitize_text_field ( $_REQUEST['plugin'] ) ) : '';
233
 
234
  $wp_plugin_slug = dirname($plugin);
235
 
vendor/otgs/installer/includes/class-installer-theme.php CHANGED
@@ -238,7 +238,7 @@ class Installer_Theme_Class {
238
  $commercial = false;
239
  if ( ('plugin-install' == $current_screen) || ('plugin-install-network' == $current_screen) ) {
240
  if ( isset($_GET['tab']) ) {
241
- $tab = $_GET['tab'];
242
  if ( 'commercial' == $tab ) {
243
  $commercial = true;
244
  }
@@ -711,14 +711,14 @@ class Installer_Theme_Class {
711
  if ( isset ($_SERVER ['REQUEST_URI']) ) {
712
  $request_uri = $_SERVER ['REQUEST_URI'];
713
  if ( isset ($_GET ['browse']) ) {
714
- $active_tab = trim( $_GET ['browse'] );
715
  $this->installer_theme_active_tab = $active_tab;
716
  } elseif ( isset ($_POST ['request'] ['browse']) ) {
717
- $active_tab = trim( $_POST ['request'] ['browse'] );
718
  $this->installer_theme_active_tab = $active_tab;
719
  } elseif ( (isset ($_GET ['theme_repo'])) && (isset ($_GET ['action'])) ) {
720
- $theme_repo = trim( $_GET ['theme_repo'] );
721
- $the_action = trim( $_GET ['action'] );
722
  if ( ('install-theme' == $the_action) && (!(empty($theme_repo))) ) {
723
  $this->installer_theme_active_tab = $theme_repo;
724
  }
@@ -854,7 +854,7 @@ class Installer_Theme_Class {
854
  check_ajax_referer( 'installer_theme_frontend_selected_tab', 'installer_theme_frontend_selected_tab_nonce' );
855
 
856
  //Client_side_active_tab
857
- $frontend_tab_selected = filter_input( INPUT_POST, 'frontend_tab_selected', FILTER_SANITIZE_FULL_SPECIAL_CHARS, FILTER_NULL_ON_FAILURE );
858
  if ( !(empty($frontend_tab_selected)) ) {
859
  //Front end tab selected
860
  update_option( 'wp_installer_clientside_active_tab', $frontend_tab_selected, false );
238
  $commercial = false;
239
  if ( ('plugin-install' == $current_screen) || ('plugin-install-network' == $current_screen) ) {
240
  if ( isset($_GET['tab']) ) {
241
+ $tab = sanitize_text_field( $_GET['tab'] );
242
  if ( 'commercial' == $tab ) {
243
  $commercial = true;
244
  }
711
  if ( isset ($_SERVER ['REQUEST_URI']) ) {
712
  $request_uri = $_SERVER ['REQUEST_URI'];
713
  if ( isset ($_GET ['browse']) ) {
714
+ $active_tab = sanitize_text_field( $_GET['browse'] );
715
  $this->installer_theme_active_tab = $active_tab;
716
  } elseif ( isset ($_POST ['request'] ['browse']) ) {
717
+ $active_tab = sanitize_text_field ( $_POST['request']['browse'] );
718
  $this->installer_theme_active_tab = $active_tab;
719
  } elseif ( (isset ($_GET ['theme_repo'])) && (isset ($_GET ['action'])) ) {
720
+ $theme_repo = sanitize_text_field( $_GET['theme_repo'] );
721
+ $the_action = sanitize_text_field( $_GET['action'] );
722
  if ( ('install-theme' == $the_action) && (!(empty($theme_repo))) ) {
723
  $this->installer_theme_active_tab = $theme_repo;
724
  }
854
  check_ajax_referer( 'installer_theme_frontend_selected_tab', 'installer_theme_frontend_selected_tab_nonce' );
855
 
856
  //Client_side_active_tab
857
+ $frontend_tab_selected = sanitize_text_field( $_POST['frontend_tab_selected'] );
858
  if ( !(empty($frontend_tab_selected)) ) {
859
  //Front end tab selected
860
  update_option( 'wp_installer_clientside_active_tab', $frontend_tab_selected, false );
vendor/otgs/installer/includes/installer.class.php CHANGED
@@ -6,13 +6,13 @@ final class WP_Installer{
6
  public $settings = array();
7
 
8
  private $repositories = array();
9
-
10
  protected $api_debug = '';
11
 
12
  private $config = array();
13
-
14
  protected $_plugins_renew_warnings = array();
15
-
16
  protected $_gz_on = false;
17
 
18
  private $admin_messages = array();
@@ -32,14 +32,14 @@ final class WP_Installer{
32
  public $dependencies;
33
 
34
  public static function instance() {
35
-
36
  if ( is_null( self::$_instance ) ) {
37
  self::$_instance = new self();
38
  }
39
-
40
  return self::$_instance;
41
  }
42
-
43
  public function __construct(){
44
 
45
  if(!is_admin() || !is_user_logged_in()) return; //Only for admin
@@ -71,28 +71,28 @@ final class WP_Installer{
71
  }
72
 
73
  // default config
74
- $this->config['plugins_install_tab'] = false;
75
-
76
  add_action('init', array($this, 'init'));
77
-
78
  //add_filter('wp_installer_buy_url', array($this, 'append_parameters_to_buy_url'));
79
 
80
  add_action('init', array($this,'load_locale'));
81
-
82
  }
83
 
84
  public function get_repositories() {
85
-
86
- return $this->repositories;
87
-
88
  }
89
-
90
  public function set_config($key, $value){
91
-
92
  $this->config[$key] = $value;
93
-
94
  }
95
-
96
  public function init(){
97
  global $pagenow;
98
 
@@ -121,12 +121,12 @@ final class WP_Installer{
121
  );
122
 
123
  wp_localize_script( 'installer-admin', 'installer_strings', $translation_array );
124
-
125
  if($pagenow == 'plugins.php'){
126
  add_action('admin_notices', array($this, 'setup_plugins_page_notices'));
127
  add_action('admin_notices', array($this, 'setup_plugins_renew_warnings'), 10);
128
  add_action('admin_notices', array($this, 'queue_plugins_renew_warnings'), 20);
129
-
130
  add_action('admin_init', array($this, 'setup_plugins_action_links'));
131
 
132
  }
@@ -139,10 +139,10 @@ final class WP_Installer{
139
  add_action('wp_ajax_save_site_key', array($this, 'save_site_key'));
140
  add_action('wp_ajax_remove_site_key', array($this, 'remove_site_key_ajax'));
141
  add_action('wp_ajax_update_site_key', array($this, 'update_site_key'));
142
-
143
  add_action('wp_ajax_installer_download_plugin', array($this, 'download_plugin_ajax_handler'));
144
  add_action('wp_ajax_installer_activate_plugin', array($this, 'activate_plugin'));
145
-
146
  add_action('wp_ajax_installer_dismiss_nag', array($this, 'dismiss_nag'));
147
  }
148
 
@@ -226,56 +226,56 @@ final class WP_Installer{
226
  add_action('install_plugins_commercial', array($this, 'show_products'));
227
  }
228
  }
229
-
230
  }
231
-
232
- public function menu_url(){
233
  if(is_multisite()){
234
  if(is_network_admin()){
235
- $url = network_admin_url('plugin-install.php?tab=commercial');
236
  }else{
237
- $url = admin_url('options-general.php?page=installer');
238
- }
239
  }else{
240
- $url = admin_url('plugin-install.php?tab=commercial');
241
  }
242
  return $url;
243
  }
244
-
245
  private function menu_multisite_redirect(){
246
  global $pagenow;
247
-
248
  if($pagenow == 'plugin-install.php' && isset($_GET['tab']) && $_GET['tab'] == 'commercial'){
249
  wp_redirect($this->menu_url());
250
  exit;
251
  }
252
-
253
- }
254
-
255
  private function _pre_1_0_clean_up(){
256
  global $wpdb;
257
-
258
  if(!defined('WPRC_VERSION')){
259
  $old_tables = array(
260
- $wpdb->prefix . 'wprc_cached_requests',
261
- $wpdb->prefix . 'wprc_extension_types',
262
- $wpdb->prefix . 'wprc_extensions',
263
- $wpdb->prefix . 'wprc_repositories',
264
- $wpdb->prefix . 'wprc_repositories_relationships',
265
  );
266
-
267
  foreach($old_tables as $table){
268
  $wpdb->query(sprintf("DROP TABLE IF EXISTS %s", $table));
269
  }
270
-
271
  }
272
-
273
  $this->settings['_pre_1_0_clean_up'] = true;
274
  $this->save_settings();
275
  }
276
-
277
  public function setup_plugins_action_links(){
278
-
279
  $plugins = get_plugins();
280
 
281
  $repositories_plugins = array();
@@ -335,16 +335,16 @@ final class WP_Installer{
335
 
336
  }
337
  }
338
-
339
  }
340
 
341
  public function plugins_action_links_registered($links){
342
  $links[] = '<a href="' . $this->menu_url() . '">' . __('Registered', 'installer') . '</a>';
343
  return $links;
344
  }
345
-
346
  public function plugins_action_links_not_registered($links){
347
- $links[] = '<a href="' . $this->menu_url() . '">' . __('Register', 'installer') . '</a>';
348
  return $links;
349
  }
350
 
@@ -389,13 +389,13 @@ final class WP_Installer{
389
  }
390
 
391
  public function version(){
392
- return WP_INSTALLER_VERSION;
393
  }
394
-
395
  public function plugin_path() {
396
  return untrailingslashit( plugin_dir_path( dirname(__FILE__) ) );
397
  }
398
-
399
  public function plugin_url() {
400
  if(isset($this->config['in_theme_folder']) && !empty($this->config['in_theme_folder'])){
401
  $url = untrailingslashit(get_template_directory_uri() . '/' . $this->config['in_theme_folder']);
@@ -412,7 +412,7 @@ final class WP_Installer{
412
  return $pagenow == 'plugin-install.php' && isset($_GET['tab']) && $_GET['tab'] == 'commercial';
413
  }
414
 
415
- public function res_url(){
416
  if(isset($this->config['in_theme_folder']) && !empty($this->config['in_theme_folder'])){
417
  $url = untrailingslashit(get_template_directory_uri() . '/' . $this->config['in_theme_folder']);
418
  }else{
@@ -420,9 +420,9 @@ final class WP_Installer{
420
  }
421
  return $url;
422
  }
423
-
424
  public function save_settings(){
425
-
426
  $_settings = serialize($this->settings);
427
  if($this->_gz_on){
428
  $_settings = gzcompress($_settings);
@@ -643,24 +643,24 @@ final class WP_Installer{
643
 
644
  return $site_url;
645
  }
646
-
647
  public function show_site_key_nags(){
648
  $screen = get_current_screen();
649
-
650
  if($screen->base == 'settings_page_installer' || ($screen->base == 'plugin-install' && isset($_GET['tab']) && $_GET['tab'] == 'commercial')){
651
  return;
652
  }
653
-
654
  if(!empty($this->config['site_key_nags'])){
655
-
656
  foreach($this->config['site_key_nags'] as $nag){
657
-
658
  if(!$this->repository_has_subscription($nag['repository_id'] )){
659
  $show = true;
660
  if(!empty($nag['condition_cb'])){
661
  $show = call_user_func($nag['condition_cb']);
662
  }
663
-
664
  if(empty($this->settings['dismissed_nags'][$nag['repository_id']]) && $show){
665
  echo '<div class="updated error otgs-is-dismissible"><p>';
666
  printf(__("To get automatic updates, you need to register %s for this site. %sRegister %s%s", 'sitepress'),
@@ -671,29 +671,29 @@ final class WP_Installer{
671
  echo '</div>';
672
  }
673
  }
674
-
675
  }
676
-
677
  }
678
-
679
  }
680
-
681
  public function dismiss_nag(){
682
  $this->settings['dismissed_nags'][$_POST['repository']] = 1;
683
-
684
  $this->save_settings();
685
-
686
  echo json_encode(array());
687
  exit;
688
  }
689
-
690
  public function add_install_plugins_tab($tabs){
691
-
692
  $tabs['commercial'] = __('Commercial', 'installer');
693
-
694
  return $tabs;
695
  }
696
-
697
  public function load_repositories_list(){
698
  global $wp_installer_instances;
699
 
@@ -735,7 +735,7 @@ final class WP_Installer{
735
  }
736
 
737
  }
738
-
739
  public function filter_repositories_list(){
740
 
741
  if(!empty($this->settings['repositories'])) {
@@ -754,8 +754,8 @@ final class WP_Installer{
754
 
755
  }
756
  }
757
-
758
-
759
  }
760
 
761
  public function refresh_repositories_data(){
@@ -793,7 +793,7 @@ final class WP_Installer{
793
  $data['products'] = preg_replace("@^https://@", 'http://', $data['products']);
794
  $response = wp_remote_get($data['products']);
795
  }
796
-
797
  if(is_wp_error($response)){
798
 
799
  $error = sprintf(__("Installer cannot contact our updates server to get information about the available products and check for new versions. If you are seeing this message for the first time, you can ignore it, as it may be a temporary communication problem. If the problem persists and your WordPress admin is slowing down, you can disable automated version checks. Add the following line to your wp-config.php file:", 'installer'), strtoupper($id));
@@ -801,27 +801,27 @@ final class WP_Installer{
801
 
802
  $this->register_admin_message($error, 'error');
803
 
804
- continue;
805
- }
806
-
807
  if($response && isset($response['response']['code']) && $response['response']['code'] == 200){
808
- $body = wp_remote_retrieve_body($response);
809
  if($body){
810
  $products = json_decode($body, true);
811
 
812
  if(is_array($products)){
813
  $this->settings['repositories'][$id]['data'] = $products;
814
  $this->settings = $this->_pre_1_6_backwards_compatibility($this->settings);
815
- }
816
- }
817
-
818
  }
819
 
820
  $this->log( sprintf("Checked for %s updates: %s", $id, $data['products']) );
821
 
822
 
823
  }
824
-
825
  // cleanup
826
  if(empty($this->settings['repositories'])){
827
  $this->settings['repositories'] = array();
@@ -839,20 +839,20 @@ final class WP_Installer{
839
  }
840
 
841
  public function show_products($args = array()){
842
-
843
  $screen = get_current_screen();
844
-
845
  if($screen->base == 'settings_page_installer'){ // settings page
846
  echo '<div class="wrap">';
847
  echo '<h2>' . __('Installer', 'installer') . '</h2>';
848
  echo '<br />';
849
  }
850
-
851
  if(!is_array($args)) $args = array();
852
  if(empty($args['template'])) $args['template'] = 'default';
853
-
854
  $this->filter_repositories_list();
855
-
856
  if(!empty($this->settings['repositories'])){
857
 
858
  $this->localize_strings();
@@ -860,34 +860,34 @@ final class WP_Installer{
860
  $this->set_hierarchy_and_order();
861
 
862
  foreach($this->settings['repositories'] as $repository_id => $repository){
863
-
864
  if($args['template'] == 'compact'){
865
-
866
  if(isset($args['repository']) && $args['repository'] == $repository_id){
867
  include $this->plugin_path() . '/templates/products-compact.php';
868
  }
869
-
870
  }else{
871
-
872
  include $this->plugin_path() . '/templates/repository-listing.php';
873
-
874
  }
875
-
876
  unset($site_key, $subscription_type, $expired, $upgrade_options, $products_avaliable);
877
-
878
  }
879
-
880
  }else{
881
-
882
  echo '<center>' . __('No repositories defined.', 'installer') . '</center>';
883
-
884
  }
885
-
886
  if($screen->base == 'settings_page_installer'){ // settings page
887
  echo '</div>';
888
  }
889
-
890
-
891
  }
892
 
893
  public function get_product_price($repository_id, $package_id, $product_id, $incl_discount = false){
@@ -1021,7 +1021,7 @@ final class WP_Installer{
1021
  public function append_parameters_to_buy_url($url, $repository_id, $args = array()){
1022
 
1023
  $url = add_query_arg( array('icl_site_url' => $this->get_installer_site_url( $repository_id ) ), $url );
1024
-
1025
  $affiliate_id = false;
1026
  $affiliate_key = false;
1027
 
@@ -1043,20 +1043,20 @@ final class WP_Installer{
1043
  }
1044
 
1045
  if(isset($this->config['affiliate_id:' . $repository_id]) && isset($this->config['affiliate_key:' . $repository_id])){
1046
-
1047
  $affiliate_id = $this->config['affiliate_id:' . $repository_id];
1048
  $affiliate_key = $this->config['affiliate_key:' . $repository_id];
1049
-
1050
  }elseif(isset($args['affiliate_id:' . $repository_id]) && isset($args['affiliate_key:' . $repository_id])){
1051
-
1052
  $affiliate_id = $args['affiliate_id:' . $repository_id];
1053
  $affiliate_key = $args['affiliate_key:' . $repository_id];
1054
-
1055
  }elseif(defined('ICL_AFFILIATE_ID') && defined('ICL_AFFILIATE_KEY')){ //support for 1 repo
1056
-
1057
- $affiliate_id = ICL_AFFILIATE_ID;
1058
- $affiliate_key = ICL_AFFILIATE_KEY;
1059
-
1060
  }elseif(isset($this->config['affiliate_id']) && isset($this->config['affiliate_key'])) {
1061
  // BACKWARDS COMPATIBILITY
1062
  $affiliate_id = $this->config['affiliate_id'];
@@ -1076,17 +1076,34 @@ final class WP_Installer{
1076
  $url = esc_url($url);
1077
 
1078
  return $url;
1079
-
1080
  }
1081
-
1082
  public function save_site_key($args = array()){
1083
-
1084
  $error = '';
1085
-
1086
- $repository_id = isset($args['repository_id']) ? $args['repository_id'] : (isset($_POST['repository_id']) ? $_POST['repository_id'] : false);
1087
- $nonce = isset($args['nonce']) ? $args['nonce'] : (isset($_POST['nonce']) ? $_POST['nonce'] : '');
1088
- $site_key = isset($args['site_key']) ? $args['site_key'] : $_POST['site_key_' . $repository_id];
1089
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1090
  $site_key = preg_replace("/[^A-Za-z0-9]/", '', $site_key);
1091
 
1092
  if($repository_id && $nonce && wp_create_nonce('save_site_key_' . $repository_id) == $nonce){
@@ -1111,22 +1128,22 @@ final class WP_Installer{
1111
  ) ;
1112
  }
1113
  }
1114
-
1115
  }
1116
-
1117
  $return = array('error' => $error);
1118
-
1119
  if($this->api_debug){
1120
- $return['debug'] = $this->api_debug;
1121
  }
1122
-
1123
  if(!empty($args['return'])){
1124
  return $return;
1125
  }else{
1126
  echo json_encode($return);
1127
  exit;
1128
  }
1129
-
1130
  }
1131
 
1132
  /**
@@ -1139,7 +1156,7 @@ final class WP_Installer{
1139
  public function get_site_key($repository_id){
1140
  return WP_Installer::get_repository_site_key( $repository_id );
1141
  }
1142
-
1143
  public function remove_site_key( $repository_id ){
1144
  if( isset( $this->settings['repositories'][$repository_id] ) ){
1145
  unset($this->settings['repositories'][$repository_id]['subscription']);
@@ -1156,7 +1173,7 @@ final class WP_Installer{
1156
  }
1157
 
1158
  public function validate_repository_subscription(){
1159
- $repository_id = isset($_GET['validate_repository']) ? $_GET['validate_repository'] : false;
1160
  if($repository_id){
1161
 
1162
  $site_key = $this->get_site_key($repository_id);
@@ -1179,12 +1196,12 @@ final class WP_Installer{
1179
  public function update_site_key(){
1180
 
1181
  $error = '';
1182
-
1183
- if($_POST['nonce'] == wp_create_nonce('update_site_key_' . $_POST['repository_id'])){
1184
-
1185
- $repository_id = $_POST['repository_id'];
1186
  $site_key = $this->get_site_key($_POST['repository_id']);
1187
-
1188
  if($site_key){
1189
  try {
1190
  $subscription_data = $this->fetch_subscription_data( $repository_id, $site_key, self::SITE_KEY_VALIDATION_SOURCE_UPDATES_CHECK );
@@ -1212,39 +1229,39 @@ final class WP_Installer{
1212
  ) ;
1213
  }
1214
  }
1215
-
1216
  }
1217
-
1218
  }
1219
-
1220
  echo json_encode(array('error' => $error));
1221
-
1222
  exit;
1223
  }
1224
-
1225
  public function api_debug_log($text){
1226
-
1227
  if(defined('WPML_DEBUG_INSTALLER') && WPML_DEBUG_INSTALLER){
1228
-
1229
  if(!is_scalar($text)){
1230
  $text = print_r($text, 1);
1231
  }
1232
-
1233
- $this->api_debug .= $text . "\n";
1234
-
1235
  }
1236
-
1237
  }
1238
-
1239
  public function fetch_subscription_data( $repository_id, $site_key, $source = self::SITE_KEY_VALIDATION_SOURCE_OTHER ){
1240
-
1241
  $subscription_data = false;
1242
 
1243
  $args['body'] = array(
1244
- 'action' => 'site_key_validation',
1245
- 'site_key' => $site_key,
1246
- 'site_url' => $this->get_installer_site_url( $repository_id ),
1247
- 'source' => $source
1248
  );
1249
 
1250
  if($repository_id == 'wpml'){
@@ -1280,9 +1297,9 @@ final class WP_Installer{
1280
 
1281
  if( !is_wp_error($response) ){
1282
  $datas = wp_remote_retrieve_body($response);
1283
-
1284
  if(is_serialized($datas)){
1285
- $data = unserialize($datas);
1286
  $this->api_debug_log($data);
1287
 
1288
  if( !empty( $data->subscription_data ) ){
@@ -1296,13 +1313,13 @@ final class WP_Installer{
1296
  }
1297
 
1298
  }else{
1299
-
1300
  $this->api_debug_log($response);
1301
  throw new Exception( $response->get_error_message() );
1302
  }
1303
 
1304
  return $subscription_data;
1305
-
1306
  }
1307
 
1308
  function get_local_product_versions( $repository_id ){
@@ -1332,164 +1349,164 @@ final class WP_Installer{
1332
 
1333
  return $versions;
1334
  }
1335
-
1336
  public function get_repository_site_key($repository_id){
1337
  $site_key = false;
1338
-
1339
  if(!empty($this->settings['repositories'][$repository_id]['subscription']['key'])){
1340
- $site_key = $this->settings['repositories'][$repository_id]['subscription']['key'];
1341
  }
1342
-
1343
  return $site_key;
1344
  }
1345
-
1346
  public function repository_has_valid_subscription($repository_id){
1347
-
1348
  $valid = false;
1349
-
1350
  if(!empty($this->settings['repositories'][$repository_id]['subscription'])){
1351
-
1352
  $subscription = $this->settings['repositories'][$repository_id]['subscription']['data'];
1353
  $valid = ( $subscription->status == 1 && (strtotime($subscription->expires) > time() || empty($subscription->expires)) ) || $subscription->status == 4;
1354
-
1355
  }
1356
  return $valid;
1357
-
1358
  }
1359
-
1360
  public function repository_has_subscription($repository_id){
1361
  $key = false;
1362
  if(!empty($this->settings['repositories'][$repository_id]['subscription']['key'])){
1363
  $key = $this->settings['repositories'][$repository_id]['subscription']['key'];
1364
  }
1365
-
1366
  return $key;
1367
-
1368
  }
1369
-
1370
  public function repository_has_expired_subscription($repository_id){
1371
-
1372
  return $this->repository_has_subscription($repository_id) && !$this->repository_has_valid_subscription($repository_id);
1373
-
1374
  }
1375
-
1376
  public function get_generic_product_name($repository_id){
1377
-
1378
  return $this->settings['repositories'][$repository_id]['data']['product-name'];
1379
-
1380
  }
1381
-
1382
  public function show_subscription_renew_warning($repository_id, $subscription_id){
1383
-
1384
  $show = false;
1385
-
1386
  $data = $this->settings['repositories'][$repository_id]['data'];
1387
  if(!empty($data['subscriptions_meta'])){
1388
  if(isset($data['subscriptions_meta']['expiration'])){
1389
-
1390
  if(!empty($data['subscriptions_meta']['expiration'][$subscription_id])){
1391
-
1392
  $days = $data['subscriptions_meta']['expiration'][$subscription_id]['days_warning'];
1393
  $message = $data['subscriptions_meta']['expiration'][$subscription_id]['warning_message'];
1394
-
1395
  }else{
1396
-
1397
  //defaults
1398
  $days = 30;
1399
  $message = __('You will have to renew your subscription in order to continue getting the updates and support.', 'installer');
1400
-
1401
  }
1402
-
1403
  if(!empty($this->settings['repositories'][$repository_id]['subscription'])){
1404
  $subscription = $this->settings['repositories'][$repository_id]['subscription'];
1405
-
1406
  if($subscription['data']->subscription_type == $subscription_id && !empty($subscription['data']->expires)){
1407
-
1408
  if(strtotime($subscription['data']->expires) < strtotime(sprintf("+%d day", $days))){
1409
-
1410
  $days_to_expiration = ceil((strtotime($subscription['data']->expires) - time()) / 86400);
1411
-
1412
  echo '<div><p class="installer-warn-box">' .
1413
- sprintf(_n('Your subscription expires in %d day.', 'Your subscription expires in %d days.', $days_to_expiration, 'installer'), $days_to_expiration) .
1414
- '<br />' . $message .
1415
- '</p></div>';
1416
-
1417
  $show = true;
1418
-
1419
  }
1420
-
1421
  }
1422
-
1423
  }
1424
-
1425
-
1426
  }
1427
  }
1428
-
1429
 
1430
  return $show;
1431
-
1432
- }
1433
-
1434
  public function setup_plugins_renew_warnings(){
1435
-
1436
  $plugins = get_plugins();
1437
-
1438
  $subscriptions_with_warnings = array();
1439
  foreach($this->settings['repositories'] as $repository_id => $repository){
1440
-
1441
  if($this->repository_has_valid_subscription($repository_id)){
1442
  $subscription_type = $this->settings['repositories'][$repository_id]['subscription']['data']->subscription_type;
1443
- $expires = $this->settings['repositories'][$repository_id]['subscription']['data']->expires;
1444
-
1445
- $never_expires = isset($this->settings['repositories'][$repository_id]['subscription'])
1446
- && empty($this->settings['repositories'][$repository_id]['subscription']['data']->expires)
1447
- && (
1448
- $this->settings['repositories'][$repository_id]['subscription']['data']->status == 4 ||
1449
- $this->settings['repositories'][$repository_id]['subscription']['data']->status == 1
1450
- );
1451
-
1452
- if(!$never_expires){
1453
  if(isset($this->settings['repositories'][$repository_id]['data']['subscriptions_meta']['expiration'][$subscription_type])){
1454
-
1455
  $days_warning = $this->settings['repositories'][$repository_id]['data']['subscriptions_meta']['expiration'][$subscription_type]['days_warning'];
1456
  $custom_message = $this->settings['repositories'][$repository_id]['data']['subscriptions_meta']['expiration'][$subscription_type]['warning_message'];
1457
-
1458
  }else{
1459
  //defaults
1460
  $days_warning = 30;
1461
  $custom_message = __('You will have to renew your subscription in order to continue getting the updates and support.', 'installer');
1462
- }
1463
-
1464
  if(strtotime($expires) < strtotime(sprintf('+%d day', $days_warning)) ){
1465
-
1466
  $days_to_expiration = ceil((strtotime($expires) - time()) / 86400);
1467
-
1468
  $message = sprintf(_n('Your subscription expires in %d day.', 'Your subscription expires in %d days.', $days_to_expiration, 'installer'), $days_to_expiration);
1469
  $subscriptions_with_warnings[$subscription_type] = $message . ' ' . $custom_message;
1470
-
1471
  }
1472
  }
1473
-
1474
  }
1475
-
1476
  }
1477
-
1478
-
1479
-
1480
  foreach($plugins as $plugin_id => $plugin){
1481
 
1482
  $slug = dirname($plugin_id);
1483
  if(empty($slug)) continue;
1484
 
1485
  foreach($this->settings['repositories'] as $repository_id => $repository){
1486
-
1487
  if($this->repository_has_valid_subscription($repository_id)){
1488
-
1489
  foreach($repository['data']['packages'] as $package){
1490
-
1491
  foreach($package['products'] as $product){
1492
-
1493
  foreach($product['plugins'] as $plugin_slug){
1494
 
1495
  $download = $this->settings['repositories'][$repository_id]['data']['downloads']['plugins'][$plugin_slug];
@@ -1497,77 +1514,77 @@ final class WP_Installer{
1497
  if($download['slug'] == $slug || $download['name'] == $plugin['Name'] || $download['name'] == $plugin['Title']){ //match order: slug, name, title
1498
 
1499
  if(isset($subscriptions_with_warnings[$product['subscription_type']])){
1500
-
1501
  $this->_plugins_renew_warnings[$plugin_id] = $subscriptions_with_warnings[$product['subscription_type']];
1502
-
1503
  }
1504
-
1505
  }
1506
-
1507
  }
1508
-
1509
  }
1510
-
1511
- }
1512
-
1513
  }
1514
-
1515
  }
1516
-
1517
  }
1518
-
1519
- }
1520
-
1521
  public function queue_plugins_renew_warnings() {
1522
-
1523
  if(!empty($this->_plugins_renew_warnings)){
1524
-
1525
  foreach($this->_plugins_renew_warnings as $plugin_id => $message){
1526
-
1527
- add_action( "after_plugin_row_" . $plugin_id, array($this, 'plugins_renew_warning'), 10, 3 );
1528
  }
1529
-
1530
  }
1531
-
1532
  }
1533
-
1534
  public function plugins_renew_warning($plugin_file, $plugin_data, $status){
1535
-
1536
  if(empty($this->_plugins_renew_warnings[$plugin_file])) return;
1537
-
1538
  $wp_list_table = _get_list_table('WP_Plugins_List_Table');
1539
  ?>
1540
-
1541
  <tr class="plugin-update-tr"><td colspan="<?php echo $wp_list_table->get_column_count(); ?>" class="plugin-update colspanchange">
1542
- <div class="update-message">
1543
- <?php
1544
- echo $this->_plugins_renew_warnings[$plugin_file]. ' ';
1545
- printf(__('%sRenew here%s.', 'installer'),
1546
- '<a href="' . $this->menu_url() . '">', '</a>');
1547
- ?>
1548
- </div>
1549
  </tr>
1550
-
1551
- <?php
1552
-
1553
  }
1554
-
1555
  public function get_subscription_type_for_repository($repository_id){
1556
 
1557
  $subscription_type = false;
1558
-
1559
  if(!empty($this->settings['repositories'][$repository_id]['subscription'])){
1560
- $subscription_type = $this->settings['repositories'][$repository_id]['subscription']['data']->subscription_type;
1561
  }
1562
-
1563
  return $subscription_type;
1564
-
1565
  }
1566
-
1567
  public function have_superior_subscription($subscription_type, $product){
1568
-
1569
  $have = false;
1570
-
1571
  if(is_array($product['upgrades'])){
1572
  foreach($product['upgrades'] as $u){
1573
  if($u['subscription_type'] == $subscription_type){
@@ -1576,10 +1593,10 @@ final class WP_Installer{
1576
  }
1577
  }
1578
  }
1579
-
1580
  return $have;
1581
  }
1582
-
1583
  public function is_product_available_for_download($product_name, $repository_id){
1584
 
1585
  $available = false;
@@ -1601,9 +1618,9 @@ final class WP_Installer{
1601
  $has_top_package = true;
1602
  if($product['name'] == $product_name){
1603
  return $available = true;
1604
- }
1605
  }
1606
-
1607
  }
1608
 
1609
  if(!empty($package['sub-packages'])){
@@ -1620,12 +1637,13 @@ final class WP_Installer{
1620
  }
1621
 
1622
  return $available;
1623
-
1624
  }
1625
 
1626
  public function get_upgrade_options($repository_id){
1627
  $all_upgrades = array();
1628
 
 
1629
  //get all products: packages and subpackages
1630
  $all_products = array();
1631
  foreach($this->settings['repositories'][$repository_id]['data']['packages'] as $package){
@@ -1644,7 +1662,7 @@ final class WP_Installer{
1644
 
1645
  }
1646
 
1647
- foreach($all_products as $product) {
1648
  if ($product['upgrades']) {
1649
  foreach ($product['upgrades'] as $upgrade) {
1650
  if ($this->repository_has_valid_subscription($repository_id) || ($this->repository_has_subscription($repository_id) && $upgrade['including_expired'])) {
@@ -1655,9 +1673,9 @@ final class WP_Installer{
1655
  }
1656
 
1657
  return $all_upgrades;
1658
-
1659
  }
1660
-
1661
  public function append_site_key_to_download_url($url, $key, $repository_id){
1662
 
1663
  $url_params['site_key'] = $key;
@@ -1684,13 +1702,13 @@ final class WP_Installer{
1684
  return $url;
1685
 
1686
  }
1687
-
1688
  public function plugin_is_installed($name, $slug, $version = null){
1689
 
1690
  $is = false;
1691
-
1692
  $plugins = get_plugins();
1693
-
1694
  foreach($plugins as $plugin_id => $plugin){
1695
 
1696
  $wp_plugin_slug = dirname($plugin_id);
@@ -1699,22 +1717,22 @@ final class WP_Installer{
1699
  if( $wp_plugin_slug == $slug || $plugin['Name'] == $name || $plugin['Title'] == $name || ( $wp_plugin_slug == $slug . '-embedded' || $plugin['Name'] == $name . ' Embedded' ) ){
1700
  if($version){
1701
  if(version_compare($plugin['Version'], $version, '>=')){
1702
- $is = $plugin['Version'];
1703
- }
1704
  }else{
1705
- $is = $plugin['Version'];
1706
  }
1707
-
1708
  break;
1709
  }
1710
-
1711
  }
1712
 
1713
  //exception: Types name difference
1714
  if(!$is && $name == 'Types'){
1715
  return $this->plugin_is_installed('Types - Complete Solution for Custom Fields and Types', $slug, $version);
1716
  }
1717
-
1718
  return $is;
1719
  }
1720
 
@@ -1757,7 +1775,7 @@ final class WP_Installer{
1757
  public function get_plugin_installed_version($name, $slug){
1758
 
1759
  return $this->plugin_is_installed($name, $slug);
1760
-
1761
  }
1762
 
1763
  public function get_plugin_repository_version($repository_id, $slug){
@@ -1766,7 +1784,7 @@ final class WP_Installer{
1766
  if(!empty($this->settings['repositories'][$repository_id]['data']['packages'])){
1767
  foreach($this->settings['repositories'][$repository_id]['data']['packages'] as $package){
1768
  foreach($package['products'] as $product) {
1769
-
1770
  foreach($product['plugins'] as $plugin_slug){
1771
 
1772
  $download = $this->settings['repositories'][$repository_id]['data']['downloads']['plugins'][$plugin_slug];
@@ -1796,12 +1814,8 @@ final class WP_Installer{
1796
 
1797
  require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
1798
  require_once $this->plugin_path() . '/includes/installer-upgrader-skins.php';
1799
-
1800
- if(isset($_POST['data'])){
1801
-
1802
- $data = json_decode( base64_decode( $_POST['data'] ), true );
1803
 
1804
- }
1805
 
1806
  $ret = false;
1807
  $plugin_id = false;
@@ -1814,14 +1828,14 @@ final class WP_Installer{
1814
  if($subscription_data && !is_wp_error($subscription_data) && $this->repository_has_valid_subscription($data['repository_id'])){
1815
 
1816
  if($data['nonce'] == wp_create_nonce('install_plugin_' . $data['url'])){
1817
-
1818
  $upgrader_skins = new Installer_Upgrader_Skins(); //use our custom (mute) Skin
1819
  $upgrader = new Plugin_Upgrader($upgrader_skins);
1820
-
1821
  remove_action( 'upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20 );
1822
-
1823
  $plugins = get_plugins();
1824
-
1825
  //upgrade or install?
1826
  foreach($plugins as $id => $plugin){
1827
  $wp_plugin_slug = dirname($id);
@@ -1830,29 +1844,29 @@ final class WP_Installer{
1830
  if($wp_plugin_slug == $data['slug'] || $is_embedded && preg_replace('/-embedded$/', '', $wp_plugin_slug) == $data['slug']){
1831
  $plugin_id = $id;
1832
  break;
1833
- }
1834
  }
1835
 
1836
  if($plugin_id && empty($is_embedded)){ //upgrade
1837
  $response['upgrade'] = 1;
1838
-
1839
  $plugin_is_active = is_plugin_active($plugin_id);
1840
 
1841
  $ret = $upgrader->upgrade($plugin_id);
1842
-
1843
  if(!$ret && !empty($upgrader->skin->installer_error)){
1844
  if(is_wp_error($upgrader->skin->installer_error)){
1845
- $message = $upgrader->skin->installer_error->get_error_message() .
1846
  ' (' . $upgrader->skin->installer_error->get_error_data() . ')';
1847
- }
1848
  }
1849
-
1850
  if($plugin_is_active){
1851
  //prevent redirects
1852
  add_filter('wp_redirect', '__return_false');
1853
  activate_plugin($plugin_id);
1854
  }
1855
-
1856
  }else{ //install
1857
 
1858
  if($is_embedded){
@@ -1860,12 +1874,12 @@ final class WP_Installer{
1860
  }
1861
 
1862
  $response['install'] = 1;
1863
- $ret = $upgrader->install($data['url']);
1864
  if(!$ret && !empty($upgrader->skin->installer_error)){
1865
  if(is_wp_error($upgrader->skin->installer_error)){
1866
- $message = $upgrader->skin->installer_error->get_error_message() .
1867
  ' (' . $upgrader->skin->installer_error->get_error_data() . ')';
1868
- }
1869
  }
1870
  }
1871
 
@@ -1878,19 +1892,19 @@ final class WP_Installer{
1878
  $plugin_version = $plugin['Version'];
1879
  $plugin_id = $id;
1880
  break;
1881
- }
1882
  }
1883
-
1884
  }
1885
-
1886
  }
1887
-
1888
  } else { //subscription not valid
1889
-
1890
  $ret = false;
1891
  $message = __('Your subscription appears to no longer be valid. Please try to register again using a valid site key.', 'installer');
1892
  }
1893
-
1894
  $response['version'] = isset($plugin_version) ? $plugin_version : 0;
1895
  $response['plugin_id'] = $plugin_id;
1896
  $response['nonce'] = wp_create_nonce('activate_' . $plugin_id);
@@ -1899,7 +1913,7 @@ final class WP_Installer{
1899
 
1900
  echo json_encode( $response );
1901
  exit;
1902
-
1903
  }
1904
 
1905
  public function download_plugin($slug, $url){
@@ -1944,12 +1958,11 @@ final class WP_Installer{
1944
  }
1945
 
1946
  public function activate_plugin(){
1947
-
1948
- $error = '';
1949
 
1950
- if(isset($_POST['nonce']) && isset($_POST['plugin_id']) && $_POST['nonce'] == wp_create_nonce('activate_' . $_POST['plugin_id'])){
1951
 
1952
- $plugin_id = $_POST['plugin_id'];
 
1953
 
1954
  // Deactivate any embedded version
1955
  $plugin_slug = dirname($plugin_id);
@@ -1968,20 +1981,20 @@ final class WP_Installer{
1968
  $return = activate_plugin($plugin_id);
1969
 
1970
  if(is_wp_error($return)){
1971
- $error = $return->get_error_message();
1972
  }
1973
-
1974
  }else{
1975
- $error = 'error';
1976
  }
1977
-
1978
  $ret = array('error' => $error);
1979
-
1980
  echo json_encode($ret);
1981
  exit;
1982
-
1983
  }
1984
-
1985
  public function custom_plugins_api_call($false, $action, $args){
1986
 
1987
  if($action == 'plugin_information'){
@@ -1998,7 +2011,7 @@ final class WP_Installer{
1998
  }
1999
 
2000
  $slug = $args->slug;
2001
-
2002
  foreach($this->settings['repositories'] as $repository_id => $repository){
2003
 
2004
  if(!$this->repository_has_valid_subscription($repository_id)){
@@ -2008,14 +2021,19 @@ final class WP_Installer{
2008
  }
2009
 
2010
  foreach($repository['data']['packages'] as $package){
2011
-
2012
  foreach($package['products'] as $product){
2013
-
2014
  foreach($product['plugins'] as $plugin_slug){
2015
 
2016
  $download = $this->settings['repositories'][$repository_id]['data']['downloads']['plugins'][$plugin_slug];
2017
 
2018
- if( $download['slug'] == $slug || $plugin_names[$slug]['name'] == $download['name'] || $plugin_names[$slug]['title'] == $download['name'] ){
 
 
 
 
 
2019
 
2020
  if( !empty( $download['free-on-wporg'] ) ){
2021
  return false; // use data from wordpress.org
@@ -2023,7 +2041,7 @@ final class WP_Installer{
2023
 
2024
  $res = new stdClass();
2025
  $res->external = true;
2026
-
2027
  $res->name = $download['name'];
2028
  $res->slug = $slug;
2029
  $res->version = $download['version'];
@@ -2039,23 +2057,23 @@ final class WP_Installer{
2039
  $res->sections = array('Description' => $download['description'], 'Changelog' => $download['changelog']);
2040
 
2041
  return $res;
2042
-
2043
  }
2044
-
2045
  }
2046
-
2047
  }
2048
-
2049
  }
2050
-
2051
  }
2052
-
2053
  }
2054
-
2055
  return $false;
2056
-
2057
  }
2058
-
2059
  public function plugins_upgrade_check($update_plugins){
2060
 
2061
  if(!empty($this->settings['repositories'])){
@@ -2063,10 +2081,10 @@ final class WP_Installer{
2063
  $plugins = get_plugins();
2064
 
2065
  foreach($plugins as $plugin_id => $plugin){
2066
-
2067
  $slug = dirname($plugin_id);
2068
  if(empty($slug)) continue;
2069
-
2070
  $version = $plugin['Version'];
2071
  $name = $plugin['Name'];
2072
 
@@ -2081,9 +2099,9 @@ final class WP_Installer{
2081
  }
2082
 
2083
  foreach($repository['data']['packages'] as $package){
2084
-
2085
  foreach($package['products'] as $product){
2086
-
2087
  foreach($product['plugins'] as $plugin_slug){
2088
 
2089
  $download = $this->settings['repositories'][$repository_id]['data']['downloads']['plugins'][$plugin_slug];
@@ -2106,48 +2124,48 @@ final class WP_Installer{
2106
  }
2107
  $update_plugins->checked[$plugin_id] = $version;
2108
  $update_plugins->response[$plugin_id] = $response;
2109
-
2110
  }
2111
-
2112
  }
2113
-
2114
  }
2115
-
2116
  }
2117
-
2118
  }
2119
-
2120
  }
2121
-
2122
  }
2123
-
2124
  return $update_plugins;
2125
-
2126
  }
2127
 
2128
  public function setup_plugins_page_notices(){
2129
-
2130
  $plugins = get_plugins();
2131
-
2132
  foreach($plugins as $plugin_id => $plugin){
2133
-
2134
  $slug = dirname($plugin_id);
2135
  if(empty($slug)) continue;
2136
-
2137
  $name = $plugin['Name'];
2138
-
2139
  foreach($this->settings['repositories'] as $repository_id => $repository){
2140
-
2141
  if(!$this->repository_has_valid_subscription($repository_id)){
2142
  $site_key = false;
2143
  }else{
2144
- $site_key = $repository['subscription']['key'];
2145
  }
2146
 
2147
  foreach($repository['data']['packages'] as $package){
2148
-
2149
  foreach($package['products'] as $product){
2150
-
2151
  foreach($product['plugins'] as $plugin_slug){
2152
 
2153
  $download = $this->settings['repositories'][$repository_id]['data']['downloads']['plugins'][$plugin_slug];
@@ -2157,23 +2175,23 @@ final class WP_Installer{
2157
  }
2158
 
2159
  if( $download['slug'] == $slug || $download['name'] == $name ){
2160
-
2161
  if( !$site_key || !$this->plugin_is_registered($repository_id, $download['slug']) ){
2162
  add_action( "after_plugin_row_" . $plugin_id, array($this, 'show_purchase_notice_under_plugin'), 10, 3 );
2163
  }
2164
-
2165
  }
2166
-
2167
  }
2168
-
2169
  }
2170
-
2171
  }
2172
-
2173
  }
2174
-
2175
- }
2176
-
2177
  }
2178
 
2179
  public function show_purchase_notice_under_plugin($plugin_file, $plugin_data, $status){
@@ -2212,7 +2230,7 @@ final class WP_Installer{
2212
  }
2213
 
2214
  }
2215
-
2216
  public function localize_strings(){
2217
 
2218
  if(!empty($this->settings['repositories'])){
@@ -2224,22 +2242,22 @@ final class WP_Installer{
2224
  if(empty($product['call2action'])){
2225
  $this->settings['repositories'][$repository_id]['data']['packages'][$package_id]['products'][$product_id]['call2action'] = $product['name'];
2226
  }
2227
-
2228
  foreach($product['upgrades'] as $idx => $upg){
2229
  if(empty($upg['call2action'])){
2230
  $this->settings['repositories'][$repository_id]['data']['packages'][$package_id]['products'][$product_id]['upgrades'][$idx]['call2action'] = $upg['name'];
2231
- }
2232
  }
2233
-
2234
  foreach($product['renewals'] as $idx => $rnw){
2235
  if(empty($rnw['call2action'])){
2236
  $this->settings['repositories'][$repository_id]['data']['packages'][$package_id]['products'][$product_id]['renewals'][$idx]['call2action'] = $rnw['name'];
2237
- }
2238
-
2239
  }
2240
-
2241
  }
2242
- }
2243
  }
2244
  }
2245
 
@@ -2247,119 +2265,119 @@ final class WP_Installer{
2247
  if(is_null($sitepress)){
2248
  return;
2249
  }
2250
-
2251
  // default strings are always in English
2252
  $user_admin_language = $sitepress->get_admin_language();
2253
-
2254
  if($user_admin_language != 'en'){
2255
  foreach($this->settings['repositories'] as $repository_id => $repository){
2256
-
2257
  $localization = $repository['data']['localization'];
2258
-
2259
  //packages
2260
  foreach($repository['data']['packages'] as $package_id => $package){
2261
-
2262
  if( isset($localization['packages'][$package_id]['name'][$user_admin_language]) ){
2263
- $this->settings['repositories'][$repository_id]['data']['packages'][$package_id]['name'] = $localization['packages'][$package_id]['name'][$user_admin_language];
2264
  }
2265
  if( isset($localization['packages'][$package_id]['description'][$user_admin_language]) ){
2266
- $this->settings['repositories'][$repository_id]['data']['packages'][$package_id]['description'] = $localization['packages'][$package_id]['description'][$user_admin_language];
2267
  }
2268
-
2269
  }
2270
-
2271
  //products
2272
  foreach($repository['data']['packages'] as $package_id => $package){
2273
  foreach($package['products'] as $product_id => $product){
2274
-
2275
  if( isset($localization['products'][$product_id]['name'][$user_admin_language]) ){
2276
- $this->settings['repositories'][$repository_id]['data']['packages'][$package_id]['products'][$product_id]['name']
2277
- = $localization['products'][$product_id]['name'][$user_admin_language];
2278
  }
2279
  if( isset($localization['products'][$product_id]['description'][$user_admin_language]) ){
2280
- $this->settings['repositories'][$repository_id]['data']['packages'][$package_id]['products'][$product_id]['description']
2281
- = $localization['products'][$product_id]['description'][$user_admin_language];
2282
  }
2283
  if( isset($localization['products'][$product_id]['call2action'][$user_admin_language]) ){
2284
- $this->settings['repositories'][$repository_id]['data']['packages'][$package_id]['products'][$product_id]['name']
2285
- = $localization['products'][$product_id]['call2action'][$user_admin_language];
2286
  }
2287
-
2288
-
2289
  }
2290
  }
2291
-
2292
  //subscription info
2293
  if(isset($repository['data']['subscriptions_meta']['expiration'])){
2294
  foreach($repository['data']['subscriptions_meta']['expiration'] as $subscription_id => $note){
2295
  if(isset($localization['subscriptions-notes'][$subscription_id]['expiration-warning'][$user_admin_language])){
2296
- $this->settings['repositories'][$repository_id]['data']['subscriptions_meta']['expiration'][$subscription_id]['warning_message']
2297
- = $localization['subscriptions-notes'][$subscription_id]['expiration-warning'][$user_admin_language];
2298
  }
2299
  }
2300
  }
2301
-
2302
  }
2303
  }
2304
-
2305
  }
2306
-
2307
  public function get_matching_cp($repository, $args = array()){
2308
  $match = false;
2309
-
2310
-
2311
  $cp_name = $cp_author = false;
2312
-
2313
  if(isset($this->config['src_name']) && isset($this->config['src_author'])){
2314
-
2315
  $cp_name = $this->config['src_name'];
2316
  $cp_author = $this->config['src_author'];
2317
-
2318
  }elseif(isset($args['src_name']) && isset($args['src_author'])){
2319
-
2320
  $cp_name = $args['src_name'];
2321
  $cp_author = $args['src_author'];
2322
-
2323
  }
2324
-
2325
  if(isset($repository['data']['marketing_cp'])){
2326
-
2327
  foreach($repository['data']['marketing_cp'] as $cp){
2328
-
2329
  if(!empty($cp['exp']) && time() > $cp['exp']){
2330
  continue;
2331
  }
2332
-
2333
  //Use theme_name for plugins too
2334
  if(!empty($cp['theme_name'])){
2335
  if($cp['author_name'] == $cp_author && $cp['theme_name'] == $cp_name){
2336
  $match = $cp;
2337
  continue;
2338
- }
2339
  }else{
2340
  if($cp['author_name'] == $cp_author){
2341
  $match = $cp;
2342
  continue;
2343
- }
2344
  }
2345
-
2346
  }
2347
-
2348
  }
2349
-
2350
  return $match;
2351
  }
2352
-
2353
  public function set_filtered_prices($args = array()){
2354
-
2355
  foreach($this->settings['repositories'] as $repository_id => $repository){
2356
-
2357
  $match = $this->get_matching_cp($repository, $args);
2358
-
2359
  if(empty($match)) continue;
2360
-
2361
  foreach($repository['data']['packages'] as $package_id => $package){
2362
-
2363
  foreach($package['products'] as $product_id => $product){
2364
 
2365
  if($match['dtp'] == '%'){
@@ -2373,13 +2391,13 @@ final class WP_Installer{
2373
 
2374
  if($fprice){
2375
  $this->settings['repositories'][$repository_id]['data']['packages'][$package_id]['products'][$product_id]['price_disc'] = $fprice;
2376
-
2377
  $url_glue = false !== strpos($this->settings['repositories'][$repository_id]['data']['packages'][$package_id]['products'][$product_id]['url'], '?') ? '&' : '?';
2378
  $cpndata = base64_encode(json_encode(array('theme_author' => $match['author_name'], 'theme_name' => $match['theme_name'], 'vlc' => $match['vlc'])));
2379
  $this->settings['repositories'][$repository_id]['data']['packages'][$package_id]['products'][$product_id]['url'] .= $url_glue . 'cpn=' . $cpndata;
2380
-
2381
  foreach($product['upgrades'] as $upgrade_id => $upgrade){
2382
-
2383
  $fprice = false;
2384
  if($match['dtp'] == '%'){
2385
  $fprice = round( $upgrade['price'] * (1 - $match['amt']/100), 2 );
@@ -2388,21 +2406,21 @@ final class WP_Installer{
2388
  $fprice = $upgrade['price'] - $match['amt'];
2389
  }
2390
  if($fprice){
2391
- $this->settings['repositories'][$repository_id]['data']['packages'][$package_id]['products'][$product_id]['upgrades'][$upgrade_id]['price_disc'] = $fprice;
2392
  $this->settings['repositories'][$repository_id]['data']['packages'][$package_id]['products'][$product_id]['upgrades'][$upgrade_id]['url'] .= $url_glue . 'cpn=' . $cpndata;
2393
  }
2394
-
2395
-
2396
  }
2397
-
2398
  }
2399
-
2400
  }
2401
-
2402
  }
2403
-
2404
  }
2405
-
2406
  }
2407
 
2408
  public function set_hierarchy_and_order(){
@@ -2478,7 +2496,7 @@ final class WP_Installer{
2478
 
2479
  if ( isset($_REQUEST['action']) ) {
2480
 
2481
- $action = isset($_REQUEST['action']) ? $_REQUEST['action'] : '';
2482
 
2483
  //bulk mode
2484
  if('update-selected' == $action) {
@@ -2567,7 +2585,7 @@ final class WP_Installer{
2567
 
2568
  if( 'upgrade-plugin' == $action || 'update-plugin' == $action ) {
2569
 
2570
- $plugin = isset($_REQUEST['plugin']) ? trim($_REQUEST['plugin']) : '';
2571
 
2572
  $wp_plugin_slug = dirname($plugin);
2573
 
6
  public $settings = array();
7
 
8
  private $repositories = array();
9
+
10
  protected $api_debug = '';
11
 
12
  private $config = array();
13
+
14
  protected $_plugins_renew_warnings = array();
15
+
16
  protected $_gz_on = false;
17
 
18
  private $admin_messages = array();
32
  public $dependencies;
33
 
34
  public static function instance() {
35
+
36
  if ( is_null( self::$_instance ) ) {
37
  self::$_instance = new self();
38
  }
39
+
40
  return self::$_instance;
41
  }
42
+
43
  public function __construct(){
44
 
45
  if(!is_admin() || !is_user_logged_in()) return; //Only for admin
71
  }
72
 
73
  // default config
74
+ $this->config['plugins_install_tab'] = false;
75
+
76
  add_action('init', array($this, 'init'));
77
+
78
  //add_filter('wp_installer_buy_url', array($this, 'append_parameters_to_buy_url'));
79
 
80
  add_action('init', array($this,'load_locale'));
81
+
82
  }
83
 
84
  public function get_repositories() {
85
+
86
+ return $this->repositories;
87
+
88
  }
89
+
90
  public function set_config($key, $value){
91
+
92
  $this->config[$key] = $value;
93
+
94
  }
95
+
96
  public function init(){
97
  global $pagenow;
98
 
121
  );
122
 
123
  wp_localize_script( 'installer-admin', 'installer_strings', $translation_array );
124
+
125
  if($pagenow == 'plugins.php'){
126
  add_action('admin_notices', array($this, 'setup_plugins_page_notices'));
127
  add_action('admin_notices', array($this, 'setup_plugins_renew_warnings'), 10);
128
  add_action('admin_notices', array($this, 'queue_plugins_renew_warnings'), 20);
129
+
130
  add_action('admin_init', array($this, 'setup_plugins_action_links'));
131
 
132
  }
139
  add_action('wp_ajax_save_site_key', array($this, 'save_site_key'));
140
  add_action('wp_ajax_remove_site_key', array($this, 'remove_site_key_ajax'));
141
  add_action('wp_ajax_update_site_key', array($this, 'update_site_key'));
142
+
143
  add_action('wp_ajax_installer_download_plugin', array($this, 'download_plugin_ajax_handler'));
144
  add_action('wp_ajax_installer_activate_plugin', array($this, 'activate_plugin'));
145
+
146
  add_action('wp_ajax_installer_dismiss_nag', array($this, 'dismiss_nag'));
147
  }
148
 
226
  add_action('install_plugins_commercial', array($this, 'show_products'));
227
  }
228
  }
229
+
230
  }
231
+
232
+ public function menu_url(){
233
  if(is_multisite()){
234
  if(is_network_admin()){
235
+ $url = network_admin_url('plugin-install.php?tab=commercial');
236
  }else{
237
+ $url = admin_url('options-general.php?page=installer');
238
+ }
239
  }else{
240
+ $url = admin_url('plugin-install.php?tab=commercial');
241
  }
242
  return $url;
243
  }
244
+
245
  private function menu_multisite_redirect(){
246
  global $pagenow;
247
+
248
  if($pagenow == 'plugin-install.php' && isset($_GET['tab']) && $_GET['tab'] == 'commercial'){
249
  wp_redirect($this->menu_url());
250
  exit;
251
  }
252
+
253
+ }
254
+
255
  private function _pre_1_0_clean_up(){
256
  global $wpdb;
257
+
258
  if(!defined('WPRC_VERSION')){
259
  $old_tables = array(
260
+ $wpdb->prefix . 'wprc_cached_requests',
261
+ $wpdb->prefix . 'wprc_extension_types',
262
+ $wpdb->prefix . 'wprc_extensions',
263
+ $wpdb->prefix . 'wprc_repositories',
264
+ $wpdb->prefix . 'wprc_repositories_relationships',
265
  );
266
+
267
  foreach($old_tables as $table){
268
  $wpdb->query(sprintf("DROP TABLE IF EXISTS %s", $table));
269
  }
270
+
271
  }
272
+
273
  $this->settings['_pre_1_0_clean_up'] = true;
274
  $this->save_settings();
275
  }
276
+
277
  public function setup_plugins_action_links(){
278
+
279
  $plugins = get_plugins();
280
 
281
  $repositories_plugins = array();
335
 
336
  }
337
  }
338
+
339
  }
340
 
341
  public function plugins_action_links_registered($links){
342
  $links[] = '<a href="' . $this->menu_url() . '">' . __('Registered', 'installer') . '</a>';
343
  return $links;
344
  }
345
+
346
  public function plugins_action_links_not_registered($links){
347
+ $links[] = '<a href="' . $this->menu_url() . '">' . __('Register', 'installer') . '</a>';
348
  return $links;
349
  }
350
 
389
  }
390
 
391
  public function version(){
392
+ return WP_INSTALLER_VERSION;
393
  }
394
+
395
  public function plugin_path() {
396
  return untrailingslashit( plugin_dir_path( dirname(__FILE__) ) );
397
  }
398
+
399
  public function plugin_url() {
400
  if(isset($this->config['in_theme_folder']) && !empty($this->config['in_theme_folder'])){
401
  $url = untrailingslashit(get_template_directory_uri() . '/' . $this->config['in_theme_folder']);
412
  return $pagenow == 'plugin-install.php' && isset($_GET['tab']) && $_GET['tab'] == 'commercial';
413
  }
414
 
415
+ public function res_url(){
416
  if(isset($this->config['in_theme_folder']) && !empty($this->config['in_theme_folder'])){
417
  $url = untrailingslashit(get_template_directory_uri() . '/' . $this->config['in_theme_folder']);
418
  }else{
420
  }
421
  return $url;
422
  }
423
+
424
  public function save_settings(){
425
+
426
  $_settings = serialize($this->settings);
427
  if($this->_gz_on){
428
  $_settings = gzcompress($_settings);
643
 
644
  return $site_url;
645
  }
646
+
647
  public function show_site_key_nags(){
648
  $screen = get_current_screen();
649
+
650
  if($screen->base == 'settings_page_installer' || ($screen->base == 'plugin-install' && isset($_GET['tab']) && $_GET['tab'] == 'commercial')){
651
  return;
652
  }
653
+
654
  if(!empty($this->config['site_key_nags'])){
655
+
656
  foreach($this->config['site_key_nags'] as $nag){
657
+
658
  if(!$this->repository_has_subscription($nag['repository_id'] )){
659
  $show = true;
660
  if(!empty($nag['condition_cb'])){
661
  $show = call_user_func($nag['condition_cb']);
662
  }
663
+
664
  if(empty($this->settings['dismissed_nags'][$nag['repository_id']]) && $show){
665
  echo '<div class="updated error otgs-is-dismissible"><p>';
666
  printf(__("To get automatic updates, you need to register %s for this site. %sRegister %s%s", 'sitepress'),
671
  echo '</div>';
672
  }
673
  }
674
+
675
  }
676
+
677
  }
678
+
679
  }
680
+
681
  public function dismiss_nag(){
682
  $this->settings['dismissed_nags'][$_POST['repository']] = 1;
683
+
684
  $this->save_settings();
685
+
686
  echo json_encode(array());
687
  exit;
688
  }
689
+
690
  public function add_install_plugins_tab($tabs){
691
+
692
  $tabs['commercial'] = __('Commercial', 'installer');
693
+
694
  return $tabs;
695
  }
696
+
697
  public function load_repositories_list(){
698
  global $wp_installer_instances;
699
 
735
  }
736
 
737
  }
738
+
739
  public function filter_repositories_list(){
740
 
741
  if(!empty($this->settings['repositories'])) {
754
 
755
  }
756
  }
757
+
758
+
759
  }
760
 
761
  public function refresh_repositories_data(){
793
  $data['products'] = preg_replace("@^https://@", 'http://', $data['products']);
794
  $response = wp_remote_get($data['products']);
795
  }
796
+
797
  if(is_wp_error($response)){
798
 
799
  $error = sprintf(__("Installer cannot contact our updates server to get information about the available products and check for new versions. If you are seeing this message for the first time, you can ignore it, as it may be a temporary communication problem. If the problem persists and your WordPress admin is slowing down, you can disable automated version checks. Add the following line to your wp-config.php file:", 'installer'), strtoupper($id));
801
 
802
  $this->register_admin_message($error, 'error');
803
 
804
+ continue;
805
+ }
806
+
807
  if($response && isset($response['response']['code']) && $response['response']['code'] == 200){
808
+ $body = wp_remote_retrieve_body($response);
809
  if($body){
810
  $products = json_decode($body, true);
811
 
812
  if(is_array($products)){
813
  $this->settings['repositories'][$id]['data'] = $products;
814
  $this->settings = $this->_pre_1_6_backwards_compatibility($this->settings);
815
+ }
816
+ }
817
+
818
  }
819
 
820
  $this->log( sprintf("Checked for %s updates: %s", $id, $data['products']) );
821
 
822
 
823
  }
824
+
825
  // cleanup
826
  if(empty($this->settings['repositories'])){
827
  $this->settings['repositories'] = array();
839
  }
840
 
841
  public function show_products($args = array()){
842
+
843
  $screen = get_current_screen();
844
+
845
  if($screen->base == 'settings_page_installer'){ // settings page
846
  echo '<div class="wrap">';
847
  echo '<h2>' . __('Installer', 'installer') . '</h2>';
848
  echo '<br />';
849
  }
850
+
851
  if(!is_array($args)) $args = array();
852
  if(empty($args['template'])) $args['template'] = 'default';
853
+
854
  $this->filter_repositories_list();
855
+
856
  if(!empty($this->settings['repositories'])){
857
 
858
  $this->localize_strings();
860
  $this->set_hierarchy_and_order();
861
 
862
  foreach($this->settings['repositories'] as $repository_id => $repository){
863
+
864
  if($args['template'] == 'compact'){
865
+
866
  if(isset($args['repository']) && $args['repository'] == $repository_id){
867
  include $this->plugin_path() . '/templates/products-compact.php';
868
  }
869
+
870
  }else{
871
+
872
  include $this->plugin_path() . '/templates/repository-listing.php';
873
+
874
  }
875
+
876
  unset($site_key, $subscription_type, $expired, $upgrade_options, $products_avaliable);
877
+
878
  }
879
+
880
  }else{
881
+
882
  echo '<center>' . __('No repositories defined.', 'installer') . '</center>';
883
+
884
  }
885
+
886
  if($screen->base == 'settings_page_installer'){ // settings page
887
  echo '</div>';
888
  }
889
+
890
+
891
  }
892
 
893
  public function get_product_price($repository_id, $package_id, $product_id, $incl_discount = false){
1021
  public function append_parameters_to_buy_url($url, $repository_id, $args = array()){
1022
 
1023
  $url = add_query_arg( array('icl_site_url' => $this->get_installer_site_url( $repository_id ) ), $url );
1024
+
1025
  $affiliate_id = false;
1026
  $affiliate_key = false;
1027
 
1043
  }
1044
 
1045
  if(isset($this->config['affiliate_id:' . $repository_id]) && isset($this->config['affiliate_key:' . $repository_id])){
1046
+
1047
  $affiliate_id = $this->config['affiliate_id:' . $repository_id];
1048
  $affiliate_key = $this->config['affiliate_key:' . $repository_id];
1049
+
1050
  }elseif(isset($args['affiliate_id:' . $repository_id]) && isset($args['affiliate_key:' . $repository_id])){
1051
+
1052
  $affiliate_id = $args['affiliate_id:' . $repository_id];
1053
  $affiliate_key = $args['affiliate_key:' . $repository_id];
1054
+
1055
  }elseif(defined('ICL_AFFILIATE_ID') && defined('ICL_AFFILIATE_KEY')){ //support for 1 repo
1056
+
1057
+ $affiliate_id = ICL_AFFILIATE_ID;
1058
+ $affiliate_key = ICL_AFFILIATE_KEY;
1059
+
1060
  }elseif(isset($this->config['affiliate_id']) && isset($this->config['affiliate_key'])) {
1061
  // BACKWARDS COMPATIBILITY
1062
  $affiliate_id = $this->config['affiliate_id'];
1076
  $url = esc_url($url);
1077
 
1078
  return $url;
1079
+
1080
  }
1081
+
1082
  public function save_site_key($args = array()){
1083
+
1084
  $error = '';
1085
+
1086
+ if( isset( $args['repository_id'] ) ){
1087
+ $repository_id = $args['repository_id'];
1088
+ }elseif( isset( $_POST['repository_id'] ) ){
1089
+ $repository_id = sanitize_text_field( $_POST['repository_id'] );
1090
+ }else{
1091
+ $repository_id = false;
1092
+ }
1093
+
1094
+ if( isset( $args['nonce'] ) ){
1095
+ $nonce = $args['nonce'];
1096
+ }elseif( isset($_POST['nonce'] ) ){
1097
+ $nonce = sanitize_text_field( $_POST['nonce'] );
1098
+ }else{
1099
+ $nonce = '';
1100
+ }
1101
+
1102
+ if( isset( $args['site_key'] ) ){
1103
+ $site_key = $args['site_key'];
1104
+ } else {
1105
+ $site_key = sanitize_text_field( $_POST[ 'site_key_' . $repository_id] );
1106
+ }
1107
  $site_key = preg_replace("/[^A-Za-z0-9]/", '', $site_key);
1108
 
1109
  if($repository_id && $nonce && wp_create_nonce('save_site_key_' . $repository_id) == $nonce){
1128
  ) ;
1129
  }
1130
  }
1131
+
1132
  }
1133
+
1134
  $return = array('error' => $error);
1135
+
1136
  if($this->api_debug){
1137
+ $return['debug'] = $this->api_debug;
1138
  }
1139
+
1140
  if(!empty($args['return'])){
1141
  return $return;
1142
  }else{
1143
  echo json_encode($return);
1144
  exit;
1145
  }
1146
+
1147
  }
1148
 
1149
  /**
1156
  public function get_site_key($repository_id){
1157
  return WP_Installer::get_repository_site_key( $repository_id );
1158
  }
1159
+
1160
  public function remove_site_key( $repository_id ){
1161
  if( isset( $this->settings['repositories'][$repository_id] ) ){
1162
  unset($this->settings['repositories'][$repository_id]['subscription']);
1173
  }
1174
 
1175
  public function validate_repository_subscription(){
1176
+ $repository_id = isset($_GET['validate_repository']) ? sanitize_text_field( $_GET['validate_repository'] ) : false;
1177
  if($repository_id){
1178
 
1179
  $site_key = $this->get_site_key($repository_id);
1196
  public function update_site_key(){
1197
 
1198
  $error = '';
1199
+
1200
+ $repository_id = sanitize_text_field ( $_POST['repository_id'] );
1201
+ if($_POST['nonce'] == wp_create_nonce('update_site_key_' . $repository_id )){
1202
+
1203
  $site_key = $this->get_site_key($_POST['repository_id']);
1204
+
1205
  if($site_key){
1206
  try {
1207
  $subscription_data = $this->fetch_subscription_data( $repository_id, $site_key, self::SITE_KEY_VALIDATION_SOURCE_UPDATES_CHECK );
1229
  ) ;
1230
  }
1231
  }
1232
+
1233
  }
1234
+
1235
  }
1236
+
1237
  echo json_encode(array('error' => $error));
1238
+
1239
  exit;
1240
  }
1241
+
1242
  public function api_debug_log($text){
1243
+
1244
  if(defined('WPML_DEBUG_INSTALLER') && WPML_DEBUG_INSTALLER){
1245
+
1246
  if(!is_scalar($text)){
1247
  $text = print_r($text, 1);
1248
  }
1249
+
1250
+ $this->api_debug .= $text . "\n";
1251
+
1252
  }
1253
+
1254
  }
1255
+
1256
  public function fetch_subscription_data( $repository_id, $site_key, $source = self::SITE_KEY_VALIDATION_SOURCE_OTHER ){
1257
+
1258
  $subscription_data = false;
1259
 
1260
  $args['body'] = array(
1261
+ 'action' => 'site_key_validation',
1262
+ 'site_key' => $site_key,
1263
+ 'site_url' => $this->get_installer_site_url( $repository_id ),
1264
+ 'source' => $source
1265
  );
1266
 
1267
  if($repository_id == 'wpml'){
1297
 
1298
  if( !is_wp_error($response) ){
1299
  $datas = wp_remote_retrieve_body($response);
1300
+
1301
  if(is_serialized($datas)){
1302
+ $data = unserialize($datas);
1303
  $this->api_debug_log($data);
1304
 
1305
  if( !empty( $data->subscription_data ) ){
1313
  }
1314
 
1315
  }else{
1316
+
1317
  $this->api_debug_log($response);
1318
  throw new Exception( $response->get_error_message() );
1319
  }
1320
 
1321
  return $subscription_data;
1322
+
1323
  }
1324
 
1325
  function get_local_product_versions( $repository_id ){
1349
 
1350
  return $versions;
1351
  }
1352
+
1353
  public function get_repository_site_key($repository_id){
1354
  $site_key = false;
1355
+
1356
  if(!empty($this->settings['repositories'][$repository_id]['subscription']['key'])){
1357
+ $site_key = $this->settings['repositories'][$repository_id]['subscription']['key'];
1358
  }
1359
+
1360
  return $site_key;
1361
  }
1362
+
1363
  public function repository_has_valid_subscription($repository_id){
1364
+
1365
  $valid = false;
1366
+
1367
  if(!empty($this->settings['repositories'][$repository_id]['subscription'])){
1368
+
1369
  $subscription = $this->settings['repositories'][$repository_id]['subscription']['data'];
1370
  $valid = ( $subscription->status == 1 && (strtotime($subscription->expires) > time() || empty($subscription->expires)) ) || $subscription->status == 4;
1371
+
1372
  }
1373
  return $valid;
1374
+
1375
  }
1376
+
1377
  public function repository_has_subscription($repository_id){
1378
  $key = false;
1379
  if(!empty($this->settings['repositories'][$repository_id]['subscription']['key'])){
1380
  $key = $this->settings['repositories'][$repository_id]['subscription']['key'];
1381
  }
1382
+
1383
  return $key;
1384
+
1385
  }
1386
+
1387
  public function repository_has_expired_subscription($repository_id){
1388
+
1389
  return $this->repository_has_subscription($repository_id) && !$this->repository_has_valid_subscription($repository_id);
1390
+
1391
  }
1392
+
1393
  public function get_generic_product_name($repository_id){
1394
+
1395
  return $this->settings['repositories'][$repository_id]['data']['product-name'];
1396
+
1397
  }
1398
+
1399
  public function show_subscription_renew_warning($repository_id, $subscription_id){
1400
+
1401
  $show = false;
1402
+
1403
  $data = $this->settings['repositories'][$repository_id]['data'];
1404
  if(!empty($data['subscriptions_meta'])){
1405
  if(isset($data['subscriptions_meta']['expiration'])){
1406
+
1407
  if(!empty($data['subscriptions_meta']['expiration'][$subscription_id])){
1408
+
1409
  $days = $data['subscriptions_meta']['expiration'][$subscription_id]['days_warning'];
1410
  $message = $data['subscriptions_meta']['expiration'][$subscription_id]['warning_message'];
1411
+
1412
  }else{
1413
+
1414
  //defaults
1415
  $days = 30;
1416
  $message = __('You will have to renew your subscription in order to continue getting the updates and support.', 'installer');
1417
+
1418
  }
1419
+
1420
  if(!empty($this->settings['repositories'][$repository_id]['subscription'])){
1421
  $subscription = $this->settings['repositories'][$repository_id]['subscription'];
1422
+
1423
  if($subscription['data']->subscription_type == $subscription_id && !empty($subscription['data']->expires)){
1424
+
1425
  if(strtotime($subscription['data']->expires) < strtotime(sprintf("+%d day", $days))){
1426
+
1427
  $days_to_expiration = ceil((strtotime($subscription['data']->expires) - time()) / 86400);
1428
+
1429
  echo '<div><p class="installer-warn-box">' .
1430
+ sprintf(_n('Your subscription expires in %d day.', 'Your subscription expires in %d days.', $days_to_expiration, 'installer'), $days_to_expiration) .
1431
+ '<br />' . $message .
1432
+ '</p></div>';
1433
+
1434
  $show = true;
1435
+
1436
  }
1437
+
1438
  }
1439
+
1440
  }
1441
+
1442
+
1443
  }
1444
  }
1445
+
1446
 
1447
  return $show;
1448
+
1449
+ }
1450
+
1451
  public function setup_plugins_renew_warnings(){
1452
+
1453
  $plugins = get_plugins();
1454
+
1455
  $subscriptions_with_warnings = array();
1456
  foreach($this->settings['repositories'] as $repository_id => $repository){
1457
+
1458
  if($this->repository_has_valid_subscription($repository_id)){
1459
  $subscription_type = $this->settings['repositories'][$repository_id]['subscription']['data']->subscription_type;
1460
+ $expires = $this->settings['repositories'][$repository_id]['subscription']['data']->expires;
1461
+
1462
+ $never_expires = isset($this->settings['repositories'][$repository_id]['subscription'])
1463
+ && empty($this->settings['repositories'][$repository_id]['subscription']['data']->expires)
1464
+ && (
1465
+ $this->settings['repositories'][$repository_id]['subscription']['data']->status == 4 ||
1466
+ $this->settings['repositories'][$repository_id]['subscription']['data']->status == 1
1467
+ );
1468
+
1469
+ if(!$never_expires){
1470
  if(isset($this->settings['repositories'][$repository_id]['data']['subscriptions_meta']['expiration'][$subscription_type])){
1471
+
1472
  $days_warning = $this->settings['repositories'][$repository_id]['data']['subscriptions_meta']['expiration'][$subscription_type]['days_warning'];
1473
  $custom_message = $this->settings['repositories'][$repository_id]['data']['subscriptions_meta']['expiration'][$subscription_type]['warning_message'];
1474
+
1475
  }else{
1476
  //defaults
1477
  $days_warning = 30;
1478
  $custom_message = __('You will have to renew your subscription in order to continue getting the updates and support.', 'installer');
1479
+ }
1480
+
1481
  if(strtotime($expires) < strtotime(sprintf('+%d day', $days_warning)) ){
1482
+
1483
  $days_to_expiration = ceil((strtotime($expires) - time()) / 86400);
1484
+
1485
  $message = sprintf(_n('Your subscription expires in %d day.', 'Your subscription expires in %d days.', $days_to_expiration, 'installer'), $days_to_expiration);
1486
  $subscriptions_with_warnings[$subscription_type] = $message . ' ' . $custom_message;
1487
+
1488
  }
1489
  }
1490
+
1491
  }
1492
+
1493
  }
1494
+
1495
+
1496
+
1497
  foreach($plugins as $plugin_id => $plugin){
1498
 
1499
  $slug = dirname($plugin_id);
1500
  if(empty($slug)) continue;
1501
 
1502
  foreach($this->settings['repositories'] as $repository_id => $repository){
1503
+
1504
  if($this->repository_has_valid_subscription($repository_id)){
1505
+
1506
  foreach($repository['data']['packages'] as $package){
1507
+
1508
  foreach($package['products'] as $product){
1509
+
1510
  foreach($product['plugins'] as $plugin_slug){
1511
 
1512
  $download = $this->settings['repositories'][$repository_id]['data']['downloads']['plugins'][$plugin_slug];
1514
  if($download['slug'] == $slug || $download['name'] == $plugin['Name'] || $download['name'] == $plugin['Title']){ //match order: slug, name, title
1515
 
1516
  if(isset($subscriptions_with_warnings[$product['subscription_type']])){
1517
+
1518
  $this->_plugins_renew_warnings[$plugin_id] = $subscriptions_with_warnings[$product['subscription_type']];
1519
+
1520
  }
1521
+
1522
  }
1523
+
1524
  }
1525
+
1526
  }
1527
+
1528
+ }
1529
+
1530
  }
1531
+
1532
  }
1533
+
1534
  }
1535
+
1536
+ }
1537
+
1538
  public function queue_plugins_renew_warnings() {
1539
+
1540
  if(!empty($this->_plugins_renew_warnings)){
1541
+
1542
  foreach($this->_plugins_renew_warnings as $plugin_id => $message){
1543
+
1544
+ add_action( "after_plugin_row_" . $plugin_id, array($this, 'plugins_renew_warning'), 10, 3 );
1545
  }
1546
+
1547
  }
1548
+
1549
  }
1550
+
1551
  public function plugins_renew_warning($plugin_file, $plugin_data, $status){
1552
+
1553
  if(empty($this->_plugins_renew_warnings[$plugin_file])) return;
1554
+
1555
  $wp_list_table = _get_list_table('WP_Plugins_List_Table');
1556
  ?>
1557
+
1558
  <tr class="plugin-update-tr"><td colspan="<?php echo $wp_list_table->get_column_count(); ?>" class="plugin-update colspanchange">
1559
+ <div class="update-message">
1560
+ <?php
1561
+ echo $this->_plugins_renew_warnings[$plugin_file]. ' ';
1562
+ printf(__('%sRenew here%s.', 'installer'),
1563
+ '<a href="' . $this->menu_url() . '">', '</a>');
1564
+ ?>
1565
+ </div>
1566
  </tr>
1567
+
1568
+ <?php
1569
+
1570
  }
1571
+
1572
  public function get_subscription_type_for_repository($repository_id){
1573
 
1574
  $subscription_type = false;
1575
+
1576
  if(!empty($this->settings['repositories'][$repository_id]['subscription'])){
1577
+ $subscription_type = $this->settings['repositories'][$repository_id]['subscription']['data']->subscription_type;
1578
  }
1579
+
1580
  return $subscription_type;
1581
+
1582
  }
1583
+
1584
  public function have_superior_subscription($subscription_type, $product){
1585
+
1586
  $have = false;
1587
+
1588
  if(is_array($product['upgrades'])){
1589
  foreach($product['upgrades'] as $u){
1590
  if($u['subscription_type'] == $subscription_type){
1593
  }
1594
  }
1595
  }
1596
+
1597
  return $have;
1598
  }
1599
+
1600
  public function is_product_available_for_download($product_name, $repository_id){
1601
 
1602
  $available = false;
1618
  $has_top_package = true;
1619
  if($product['name'] == $product_name){
1620
  return $available = true;
1621
+ }
1622
  }
1623
+
1624
  }
1625
 
1626
  if(!empty($package['sub-packages'])){
1637
  }
1638
 
1639
  return $available;
1640
+
1641
  }
1642
 
1643
  public function get_upgrade_options($repository_id){
1644
  $all_upgrades = array();
1645
 
1646
+
1647
  //get all products: packages and subpackages
1648
  $all_products = array();
1649
  foreach($this->settings['repositories'][$repository_id]['data']['packages'] as $package){
1662
 
1663
  }
1664
 
1665
+ foreach( $all_products as $product ) {
1666
  if ($product['upgrades']) {
1667
  foreach ($product['upgrades'] as $upgrade) {
1668
  if ($this->repository_has_valid_subscription($repository_id) || ($this->repository_has_subscription($repository_id) && $upgrade['including_expired'])) {
1673
  }
1674
 
1675
  return $all_upgrades;
1676
+
1677
  }
1678
+
1679
  public function append_site_key_to_download_url($url, $key, $repository_id){
1680
 
1681
  $url_params['site_key'] = $key;
1702
  return $url;
1703
 
1704
  }
1705
+
1706
  public function plugin_is_installed($name, $slug, $version = null){
1707
 
1708
  $is = false;
1709
+
1710
  $plugins = get_plugins();
1711
+
1712
  foreach($plugins as $plugin_id => $plugin){
1713
 
1714
  $wp_plugin_slug = dirname($plugin_id);
1717
  if( $wp_plugin_slug == $slug || $plugin['Name'] == $name || $plugin['Title'] == $name || ( $wp_plugin_slug == $slug . '-embedded' || $plugin['Name'] == $name . ' Embedded' ) ){
1718
  if($version){
1719
  if(version_compare($plugin['Version'], $version, '>=')){
1720
+ $is = $plugin['Version'];
1721
+ }
1722
  }else{
1723
+ $is = $plugin['Version'];
1724
  }
1725
+
1726
  break;
1727
  }
1728
+
1729
  }
1730
 
1731
  //exception: Types name difference
1732
  if(!$is && $name == 'Types'){
1733
  return $this->plugin_is_installed('Types - Complete Solution for Custom Fields and Types', $slug, $version);
1734
  }
1735
+
1736
  return $is;
1737
  }
1738
 
1775
  public function get_plugin_installed_version($name, $slug){
1776
 
1777
  return $this->plugin_is_installed($name, $slug);
1778
+
1779
  }
1780
 
1781
  public function get_plugin_repository_version($repository_id, $slug){
1784
  if(!empty($this->settings['repositories'][$repository_id]['data']['packages'])){
1785
  foreach($this->settings['repositories'][$repository_id]['data']['packages'] as $package){
1786
  foreach($package['products'] as $product) {
1787
+
1788
  foreach($product['plugins'] as $plugin_slug){
1789
 
1790
  $download = $this->settings['repositories'][$repository_id]['data']['downloads']['plugins'][$plugin_slug];
1814
 
1815
  require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
1816
  require_once $this->plugin_path() . '/includes/installer-upgrader-skins.php';
 
 
 
 
1817
 
1818
+ $data = json_decode( base64_decode( sanitize_text_field ( $_POST['data'] ) ), true );
1819
 
1820
  $ret = false;
1821
  $plugin_id = false;
1828
  if($subscription_data && !is_wp_error($subscription_data) && $this->repository_has_valid_subscription($data['repository_id'])){
1829
 
1830
  if($data['nonce'] == wp_create_nonce('install_plugin_' . $data['url'])){
1831
+
1832
  $upgrader_skins = new Installer_Upgrader_Skins(); //use our custom (mute) Skin
1833
  $upgrader = new Plugin_Upgrader($upgrader_skins);
1834
+
1835
  remove_action( 'upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20 );
1836
+
1837
  $plugins = get_plugins();
1838
+
1839
  //upgrade or install?
1840
  foreach($plugins as $id => $plugin){
1841
  $wp_plugin_slug = dirname($id);
1844
  if($wp_plugin_slug == $data['slug'] || $is_embedded && preg_replace('/-embedded$/', '', $wp_plugin_slug) == $data['slug']){
1845
  $plugin_id = $id;
1846
  break;
1847
+ }
1848
  }
1849
 
1850
  if($plugin_id && empty($is_embedded)){ //upgrade
1851
  $response['upgrade'] = 1;
1852
+
1853
  $plugin_is_active = is_plugin_active($plugin_id);
1854
 
1855
  $ret = $upgrader->upgrade($plugin_id);
1856
+
1857
  if(!$ret && !empty($upgrader->skin->installer_error)){
1858
  if(is_wp_error($upgrader->skin->installer_error)){
1859
+ $message = $upgrader->skin->installer_error->get_error_message() .
1860
  ' (' . $upgrader->skin->installer_error->get_error_data() . ')';
1861
+ }
1862
  }
1863
+
1864
  if($plugin_is_active){
1865
  //prevent redirects
1866
  add_filter('wp_redirect', '__return_false');
1867
  activate_plugin($plugin_id);
1868
  }
1869
+
1870
  }else{ //install
1871
 
1872
  if($is_embedded){
1874
  }
1875
 
1876
  $response['install'] = 1;
1877
+ $ret = $upgrader->install($data['url']);
1878
  if(!$ret && !empty($upgrader->skin->installer_error)){
1879
  if(is_wp_error($upgrader->skin->installer_error)){
1880
+ $message = $upgrader->skin->installer_error->get_error_message() .
1881
  ' (' . $upgrader->skin->installer_error->get_error_data() . ')';
1882
+ }
1883
  }
1884
  }
1885
 
1892
  $plugin_version = $plugin['Version'];
1893
  $plugin_id = $id;
1894
  break;
1895
+ }
1896
  }
1897
+
1898
  }
1899
+
1900
  }
1901
+
1902
  } else { //subscription not valid
1903
+
1904
  $ret = false;
1905
  $message = __('Your subscription appears to no longer be valid. Please try to register again using a valid site key.', 'installer');
1906
  }
1907
+
1908
  $response['version'] = isset($plugin_version) ? $plugin_version : 0;
1909
  $response['plugin_id'] = $plugin_id;
1910
  $response['nonce'] = wp_create_nonce('activate_' . $plugin_id);
1913
 
1914
  echo json_encode( $response );
1915
  exit;
1916
+
1917
  }
1918
 
1919
  public function download_plugin($slug, $url){
1958
  }
1959
 
1960
  public function activate_plugin(){
 
 
1961
 
1962
+ $error = '';
1963
 
1964
+ $plugin_id = sanitize_text_field ( $_POST['plugin_id'] );
1965
+ if(isset($_POST['nonce']) && $plugin_id && $_POST['nonce'] == wp_create_nonce('activate_' . $plugin_id )){
1966
 
1967
  // Deactivate any embedded version
1968
  $plugin_slug = dirname($plugin_id);
1981
  $return = activate_plugin($plugin_id);
1982
 
1983
  if(is_wp_error($return)){
1984
+ $error = $return->get_error_message();
1985
  }
1986
+
1987
  }else{
1988
+ $error = 'error';
1989
  }
1990
+
1991
  $ret = array('error' => $error);
1992
+
1993
  echo json_encode($ret);
1994
  exit;
1995
+
1996
  }
1997
+
1998
  public function custom_plugins_api_call($false, $action, $args){
1999
 
2000
  if($action == 'plugin_information'){
2011
  }
2012
 
2013
  $slug = $args->slug;
2014
+
2015
  foreach($this->settings['repositories'] as $repository_id => $repository){
2016
 
2017
  if(!$this->repository_has_valid_subscription($repository_id)){
2021
  }
2022
 
2023
  foreach($repository['data']['packages'] as $package){
2024
+
2025
  foreach($package['products'] as $product){
2026
+
2027
  foreach($product['plugins'] as $plugin_slug){
2028
 
2029
  $download = $this->settings['repositories'][$repository_id]['data']['downloads']['plugins'][$plugin_slug];
2030
 
2031
+ if( $download['slug'] == $slug ||
2032
+ isset( $plugin_names[$slug] ) && (
2033
+ $plugin_names[$slug]['name'] == $download['name'] ||
2034
+ $plugin_names[$slug]['title'] == $download['name']
2035
+ )
2036
+ ){
2037
 
2038
  if( !empty( $download['free-on-wporg'] ) ){
2039
  return false; // use data from wordpress.org
2041
 
2042
  $res = new stdClass();
2043
  $res->external = true;
2044
+
2045
  $res->name = $download['name'];
2046
  $res->slug = $slug;
2047
  $res->version = $download['version'];
2057
  $res->sections = array('Description' => $download['description'], 'Changelog' => $download['changelog']);
2058
 
2059
  return $res;
2060
+
2061
  }
2062
+
2063
  }
2064
+
2065
  }
2066
+
2067
  }
2068
+
2069
  }
2070
+
2071
  }
2072
+
2073
  return $false;
2074
+
2075
  }
2076
+
2077
  public function plugins_upgrade_check($update_plugins){
2078
 
2079
  if(!empty($this->settings['repositories'])){
2081
  $plugins = get_plugins();
2082
 
2083
  foreach($plugins as $plugin_id => $plugin){
2084
+
2085
  $slug = dirname($plugin_id);
2086
  if(empty($slug)) continue;
2087
+
2088
  $version = $plugin['Version'];
2089
  $name = $plugin['Name'];
2090
 
2099
  }
2100
 
2101
  foreach($repository['data']['packages'] as $package){
2102
+
2103
  foreach($package['products'] as $product){
2104
+
2105
  foreach($product['plugins'] as $plugin_slug){
2106
 
2107
  $download = $this->settings['repositories'][$repository_id]['data']['downloads']['plugins'][$plugin_slug];
2124
  }
2125
  $update_plugins->checked[$plugin_id] = $version;
2126
  $update_plugins->response[$plugin_id] = $response;
2127
+
2128
  }
2129
+
2130
  }
2131
+
2132
  }
2133
+
2134
  }
2135
+
2136
  }
2137
+
2138
  }
2139
+
2140
  }
2141
+
2142
  return $update_plugins;
2143
+
2144
  }
2145
 
2146
  public function setup_plugins_page_notices(){
2147
+
2148
  $plugins = get_plugins();
2149
+
2150
  foreach($plugins as $plugin_id => $plugin){
2151
+
2152
  $slug = dirname($plugin_id);
2153
  if(empty($slug)) continue;
2154
+
2155
  $name = $plugin['Name'];
2156
+
2157
  foreach($this->settings['repositories'] as $repository_id => $repository){
2158
+
2159
  if(!$this->repository_has_valid_subscription($repository_id)){
2160
  $site_key = false;
2161
  }else{
2162
+ $site_key = $repository['subscription']['key'];
2163
  }
2164
 
2165
  foreach($repository['data']['packages'] as $package){
2166
+
2167
  foreach($package['products'] as $product){
2168
+
2169
  foreach($product['plugins'] as $plugin_slug){
2170
 
2171
  $download = $this->settings['repositories'][$repository_id]['data']['downloads']['plugins'][$plugin_slug];
2175
  }
2176
 
2177
  if( $download['slug'] == $slug || $download['name'] == $name ){
2178
+
2179
  if( !$site_key || !$this->plugin_is_registered($repository_id, $download['slug']) ){
2180
  add_action( "after_plugin_row_" . $plugin_id, array($this, 'show_purchase_notice_under_plugin'), 10, 3 );
2181
  }
2182
+
2183
  }
2184
+
2185
  }
2186
+
2187
  }
2188
+
2189
  }
2190
+
2191
  }
2192
+
2193
+ }
2194
+
2195
  }
2196
 
2197
  public function show_purchase_notice_under_plugin($plugin_file, $plugin_data, $status){
2230
  }
2231
 
2232
  }
2233
+
2234
  public function localize_strings(){
2235
 
2236
  if(!empty($this->settings['repositories'])){
2242
  if(empty($product['call2action'])){
2243
  $this->settings['repositories'][$repository_id]['data']['packages'][$package_id]['products'][$product_id]['call2action'] = $product['name'];
2244
  }
2245
+
2246
  foreach($product['upgrades'] as $idx => $upg){
2247
  if(empty($upg['call2action'])){
2248
  $this->settings['repositories'][$repository_id]['data']['packages'][$package_id]['products'][$product_id]['upgrades'][$idx]['call2action'] = $upg['name'];
2249
+ }
2250
  }
2251
+
2252
  foreach($product['renewals'] as $idx => $rnw){
2253
  if(empty($rnw['call2action'])){
2254
  $this->settings['repositories'][$repository_id]['data']['packages'][$package_id]['products'][$product_id]['renewals'][$idx]['call2action'] = $rnw['name'];
2255
+ }
2256
+
2257
  }
2258
+
2259
  }
2260
+ }
2261
  }
2262
  }
2263
 
2265
  if(is_null($sitepress)){
2266
  return;
2267
  }
2268
+
2269
  // default strings are always in English
2270
  $user_admin_language = $sitepress->get_admin_language();
2271
+
2272
  if($user_admin_language != 'en'){
2273
  foreach($this->settings['repositories'] as $repository_id => $repository){
2274
+
2275
  $localization = $repository['data']['localization'];
2276
+
2277
  //packages
2278
  foreach($repository['data']['packages'] as $package_id => $package){
2279
+
2280
  if( isset($localization['packages'][$package_id]['name'][$user_admin_language]) ){
2281
+ $this->settings['repositories'][$repository_id]['data']['packages'][$package_id]['name'] = $localization['packages'][$package_id]['name'][$user_admin_language];
2282
  }
2283
  if( isset($localization['packages'][$package_id]['description'][$user_admin_language]) ){
2284
+ $this->settings['repositories'][$repository_id]['data']['packages'][$package_id]['description'] = $localization['packages'][$package_id]['description'][$user_admin_language];
2285
  }
2286
+
2287
  }
2288
+
2289
  //products
2290
  foreach($repository['data']['packages'] as $package_id => $package){
2291
  foreach($package['products'] as $product_id => $product){
2292
+
2293
  if( isset($localization['products'][$product_id]['name'][$user_admin_language]) ){
2294
+ $this->settings['repositories'][$repository_id]['data']['packages'][$package_id]['products'][$product_id]['name']
2295
+ = $localization['products'][$product_id]['name'][$user_admin_language];
2296
  }
2297
  if( isset($localization['products'][$product_id]['description'][$user_admin_language]) ){
2298
+ $this->settings['repositories'][$repository_id]['data']['packages'][$package_id]['products'][$product_id]['description']
2299
+ = $localization['products'][$product_id]['description'][$user_admin_language];
2300
  }
2301
  if( isset($localization['products'][$product_id]['call2action'][$user_admin_language]) ){
2302
+ $this->settings['repositories'][$repository_id]['data']['packages'][$package_id]['products'][$product_id]['name']
2303
+ = $localization['products'][$product_id]['call2action'][$user_admin_language];
2304
  }
2305
+
2306
+
2307
  }
2308
  }
2309
+
2310
  //subscription info
2311
  if(isset($repository['data']['subscriptions_meta']['expiration'])){
2312
  foreach($repository['data']['subscriptions_meta']['expiration'] as $subscription_id => $note){
2313
  if(isset($localization['subscriptions-notes'][$subscription_id]['expiration-warning'][$user_admin_language])){
2314
+ $this->settings['repositories'][$repository_id]['data']['subscriptions_meta']['expiration'][$subscription_id]['warning_message']
2315
+ = $localization['subscriptions-notes'][$subscription_id]['expiration-warning'][$user_admin_language];
2316
  }
2317
  }
2318
  }
2319
+
2320
  }
2321
  }
2322
+
2323
  }
2324
+
2325
  public function get_matching_cp($repository, $args = array()){
2326
  $match = false;
2327
+
2328
+
2329
  $cp_name = $cp_author = false;
2330
+
2331
  if(isset($this->config['src_name']) && isset($this->config['src_author'])){
2332
+
2333
  $cp_name = $this->config['src_name'];
2334
  $cp_author = $this->config['src_author'];
2335
+
2336
  }elseif(isset($args['src_name']) && isset($args['src_author'])){
2337
+
2338
  $cp_name = $args['src_name'];
2339
  $cp_author = $args['src_author'];
2340
+
2341
  }
2342
+
2343
  if(isset($repository['data']['marketing_cp'])){
2344
+
2345
  foreach($repository['data']['marketing_cp'] as $cp){
2346
+
2347
  if(!empty($cp['exp']) && time() > $cp['exp']){
2348
  continue;
2349
  }
2350
+
2351
  //Use theme_name for plugins too
2352
  if(!empty($cp['theme_name'])){
2353
  if($cp['author_name'] == $cp_author && $cp['theme_name'] == $cp_name){
2354
  $match = $cp;
2355
  continue;
2356
+ }
2357
  }else{
2358
  if($cp['author_name'] == $cp_author){
2359
  $match = $cp;
2360
  continue;
2361
+ }
2362
  }
2363
+
2364
  }
2365
+
2366
  }
2367
+
2368
  return $match;
2369
  }
2370
+
2371
  public function set_filtered_prices($args = array()){
2372
+
2373
  foreach($this->settings['repositories'] as $repository_id => $repository){
2374
+
2375
  $match = $this->get_matching_cp($repository, $args);
2376
+
2377
  if(empty($match)) continue;
2378
+
2379
  foreach($repository['data']['packages'] as $package_id => $package){
2380
+
2381
  foreach($package['products'] as $product_id => $product){
2382
 
2383
  if($match['dtp'] == '%'){
2391
 
2392
  if($fprice){
2393
  $this->settings['repositories'][$repository_id]['data']['packages'][$package_id]['products'][$product_id]['price_disc'] = $fprice;
2394
+
2395
  $url_glue = false !== strpos($this->settings['repositories'][$repository_id]['data']['packages'][$package_id]['products'][$product_id]['url'], '?') ? '&' : '?';
2396
  $cpndata = base64_encode(json_encode(array('theme_author' => $match['author_name'], 'theme_name' => $match['theme_name'], 'vlc' => $match['vlc'])));
2397
  $this->settings['repositories'][$repository_id]['data']['packages'][$package_id]['products'][$product_id]['url'] .= $url_glue . 'cpn=' . $cpndata;
2398
+
2399
  foreach($product['upgrades'] as $upgrade_id => $upgrade){
2400
+
2401
  $fprice = false;
2402
  if($match['dtp'] == '%'){
2403
  $fprice = round( $upgrade['price'] * (1 - $match['amt']/100), 2 );
2406
  $fprice = $upgrade['price'] - $match['amt'];
2407
  }
2408
  if($fprice){
2409
+ $this->settings['repositories'][$repository_id]['data']['packages'][$package_id]['products'][$product_id]['upgrades'][$upgrade_id]['price_disc'] = $fprice;
2410
  $this->settings['repositories'][$repository_id]['data']['packages'][$package_id]['products'][$product_id]['upgrades'][$upgrade_id]['url'] .= $url_glue . 'cpn=' . $cpndata;
2411
  }
2412
+
2413
+
2414
  }
2415
+
2416
  }
2417
+
2418
  }
2419
+
2420
  }
2421
+
2422
  }
2423
+
2424
  }
2425
 
2426
  public function set_hierarchy_and_order(){
2496
 
2497
  if ( isset($_REQUEST['action']) ) {
2498
 
2499
+ $action = isset($_REQUEST['action']) ? sanitize_text_field ( $_REQUEST['action'] ) : '';
2500
 
2501
  //bulk mode
2502
  if('update-selected' == $action) {
2585
 
2586
  if( 'upgrade-plugin' == $action || 'update-plugin' == $action ) {
2587
 
2588
+ $plugin = isset($_REQUEST['plugin']) ? trim( sanitize_text_field ( $_REQUEST['plugin'] ) ) : '';
2589
 
2590
  $wp_plugin_slug = dirname($plugin);
2591
 
vendor/otgs/installer/installer.php CHANGED
@@ -1,5 +1,5 @@
1
  <?php
2
- define('WP_INSTALLER_VERSION', '1.7.12');
3
 
4
  include_once dirname(__FILE__) . '/includes/installer.class.php';
5
 
1
  <?php
2
+ define('WP_INSTALLER_VERSION', '1.7.13');
3
 
4
  include_once dirname(__FILE__) . '/includes/installer.class.php';
5
 
vendor/otgs/installer/loader.php CHANGED
@@ -19,7 +19,7 @@ $wp_installer_instance = dirname(__FILE__) . '/installer.php';
19
  global $wp_installer_instances;
20
  $wp_installer_instances[$wp_installer_instance] = array(
21
  'bootfile' => $wp_installer_instance,
22
- 'version' => '1.7.12'
23
  );
24
 
25
 
19
  global $wp_installer_instances;
20
  $wp_installer_instances[$wp_installer_instance] = array(
21
  'bootfile' => $wp_installer_instance,
22
+ 'version' => '1.7.13'
23
  );
24
 
25
 
vendor/otgs/installer/res/js/admin.js CHANGED
@@ -24,7 +24,6 @@
24
  var data = otgs_wp_installer.getQueryParameters(settings.data);
25
  if(typeof data.action != 'undefined' && data.action == 'update-plugin'){
26
  response = xhr.responseJSON.data;
27
- console.log(typeof response.error);
28
  if(typeof response.error != 'undefined'){
29
  var default_error = jQuery('#' + response.slug + '-update .update-message').html();
30
  jQuery('#' + response.slug + '-update .update-message').html(default_error + ' &raquo;<span class="installer-red-text"> ' + response.error + '</span>');
24
  var data = otgs_wp_installer.getQueryParameters(settings.data);
25
  if(typeof data.action != 'undefined' && data.action == 'update-plugin'){
26
  response = xhr.responseJSON.data;
 
27
  if(typeof response.error != 'undefined'){
28
  var default_error = jQuery('#' + response.slug + '-update .update-message').html();
29
  jQuery('#' + response.slug + '-update .update-message').html(default_error + ' &raquo;<span class="installer-red-text"> ' + response.error + '</span>');
vendor/otgs/installer/templates/repository-listing.php CHANGED
@@ -50,7 +50,6 @@
50
 
51
  $site_key = $this->settings['repositories'][$repository_id]['subscription']['key'];
52
  $subscription_type = $this->get_subscription_type_for_repository($repository_id);
53
-
54
  $upgrade_options = $this->get_upgrade_options($repository_id);
55
  $expired = false;
56
 
50
 
51
  $site_key = $this->settings['repositories'][$repository_id]['subscription']['key'];
52
  $subscription_type = $this->get_subscription_type_for_repository($repository_id);
 
53
  $upgrade_options = $this->get_upgrade_options($repository_id);
54
  $expired = false;
55
 
wpml-config.xml CHANGED
@@ -133,4 +133,4 @@
133
  <key name="woocommerce_email_from_name"/>
134
  <key name="woocommerce_email_from_address" />
135
  </admin-texts>
136
- </wpml-config>
133
  <key name="woocommerce_email_from_name"/>
134
  <key name="woocommerce_email_from_address" />
135
  </admin-texts>
136
+ </wpml-config>
wpml-woocommerce.php CHANGED
@@ -6,12 +6,12 @@
6
  Author: OnTheGoSystems
7
  Author URI: http://www.onthegosystems.com/
8
  Text Domain: woocommerce-multilingual
9
- Version: 3.9.5
10
  */
11
 
12
  if( defined( 'WCML_VERSION' ) ) return;
13
 
14
- define( 'WCML_VERSION', '3.9.5' );
15
  define( 'WCML_PLUGIN_PATH', dirname( __FILE__ ) );
16
  define( 'WCML_PLUGIN_FOLDER', basename( WCML_PLUGIN_PATH ) );
17
  define( 'WCML_LOCALE_PATH', WCML_PLUGIN_PATH . '/locale' );
@@ -20,8 +20,13 @@ define( 'WCML_PLUGIN_URL', untrailingslashit( plugin_dir_url( __FILE__ ) ) );
20
 
21
  include WCML_PLUGIN_PATH . '/inc/constants.php';
22
  require WCML_PLUGIN_PATH . '/inc/missing-php-functions.php';
 
23
  include WCML_PLUGIN_PATH . '/inc/installer-loader.php';
24
  include WCML_PLUGIN_PATH . '/inc/wcml-core-functions.php';
 
 
 
 
25
 
26
  if ( version_compare( PHP_VERSION, '5.3.0' ) >= 0 ) {
27
  require WCML_PLUGIN_PATH . '/vendor/autoload.php';
@@ -39,6 +44,4 @@ function wpml_wcml_startup(){
39
  global $woocommerce_wpml;
40
  $woocommerce_wpml = new woocommerce_wpml();
41
  }
42
- }
43
-
44
-
6
  Author: OnTheGoSystems
7
  Author URI: http://www.onthegosystems.com/
8
  Text Domain: woocommerce-multilingual
9
+ Version: 4.0.0
10
  */
11
 
12
  if( defined( 'WCML_VERSION' ) ) return;
13
 
14
+ define( 'WCML_VERSION', '4.0.0' );
15
  define( 'WCML_PLUGIN_PATH', dirname( __FILE__ ) );
16
  define( 'WCML_PLUGIN_FOLDER', basename( WCML_PLUGIN_PATH ) );
17
  define( 'WCML_LOCALE_PATH', WCML_PLUGIN_PATH . '/locale' );
20
 
21
  include WCML_PLUGIN_PATH . '/inc/constants.php';
22
  require WCML_PLUGIN_PATH . '/inc/missing-php-functions.php';
23
+ require WCML_PLUGIN_PATH . '/inc/deprecated-WC-functions.php';
24
  include WCML_PLUGIN_PATH . '/inc/installer-loader.php';
25
  include WCML_PLUGIN_PATH . '/inc/wcml-core-functions.php';
26
+ include WCML_PLUGIN_PATH . '/inc/wcml-cart-switch-lang-functions.php';
27
+
28
+ //for language switching need call as soon as possible
29
+ $wcml_cart_switch_lang_functions = new WCML_Cart_Switch_Lang_Functions();
30
 
31
  if ( version_compare( PHP_VERSION, '5.3.0' ) >= 0 ) {
32
  require WCML_PLUGIN_PATH . '/vendor/autoload.php';
44
  global $woocommerce_wpml;
45
  $woocommerce_wpml = new woocommerce_wpml();
46
  }
47
+ }