Version Description
- The Events Calendar: convert currency for event_cost.
- Wrong product price set after purchase in combination with custom prices for secondary currency and enabled stock
- Translated attributes not saving if original one contains umlauts and original product language is German or Danish
- Price not auto-calculated if you selected using custom prices and don't set a price
- After quick edit variable product variations incremented their IDs
- Added new wcml_translate_shipping_method_in_package filter
- Products not filtered by current language while search Upsells/Cross-sells on product edit screen
- Use default language if admin user not exists while sending "New Order" email to admins
- Variation description not saved on installs with 300+ variations for product
Download this release
Release Info
Developer | sergey.r |
Plugin | WooCommerce Multilingual – run WooCommerce with WPML |
Version | 4.6.5 |
Comparing to | |
See all releases |
Code changes from version 4.6.3 to 4.6.5
- changelog/4.6.5.md +14 -0
- inc/class-wcml-attributes.php +2 -2
- inc/class-wcml-emails.php +1 -1
- inc/class-wcml-orders.php +10 -5
- inc/class-wcml-products.php +59 -46
- inc/class-wcml-wc-shipping.php +3 -1
- inc/currencies/class-wcml-custom-prices.php +62 -39
- inc/currencies/class-wcml-multi-currency.php +1 -0
- inc/translation-editor/class-wcml-synchronize-product-data.php +2 -2
- readme.txt +12 -1
- vendor/autoload.php +1 -1
- vendor/autoload_52.php +1 -1
- vendor/composer/autoload_real.php +7 -7
- vendor/composer/autoload_real_52.php +3 -3
- vendor/composer/autoload_static.php +5 -5
- wpml-woocommerce.php +2 -2
changelog/4.6.5.md
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Features
|
2 |
+
* [wcml-2780] The Events Calendar: convert currency for event_cost.
|
3 |
+
|
4 |
+
# Fixes
|
5 |
+
* [wcml-2817] Wrong product price set after purchase in combination with custom prices for secondary currency and enabled stock
|
6 |
+
* [wcml-2815] Translated attributes not saving if original one contains umlauts and original product language is German or Danish
|
7 |
+
* [wcml-2813] Price not auto-calculated if you selected using custom prices and don't set a price
|
8 |
+
* [wcml-2812] After quick edit variable product variations incremented their IDs
|
9 |
+
* [wcml-2811] Added new wcml_translate_shipping_method_in_package filter
|
10 |
+
* [wcml-2810] Products not filtered by current language while search Upsells/Cross-sells on product edit screen
|
11 |
+
* [wcml-2798] added comp. class to cover price update when products are edited with WOOBE plugin
|
12 |
+
* [wcml-2797] Use default language if admin user not exists while sending "New Order" email to admins
|
13 |
+
* [wcml-2791] Variation description not saved on installs with 300+ variations for product
|
14 |
+
* [wcml-2784] "Hide completed" switcher from Translation Editor
|
inc/class-wcml-attributes.php
CHANGED
@@ -235,7 +235,7 @@ class WCML_Attributes{
|
|
235 |
$trnsl_labels = $this->get_attr_label_translations( $tr_product_id );
|
236 |
|
237 |
foreach ( $orig_product_attrs as $key => $orig_product_attr ) {
|
238 |
-
$sanitized_key =
|
239 |
if( $sanitized_key != $key ) {
|
240 |
$orig_product_attrs_buff = $orig_product_attrs[ $key ];
|
241 |
unset( $orig_product_attrs[ $key ] );
|
@@ -537,7 +537,7 @@ class WCML_Attributes{
|
|
537 |
*/
|
538 |
function filter_attribute_name( $attribute_name, $product_id, $return_sanitized = false ) {
|
539 |
|
540 |
-
if (
|
541 |
$orig_lang = $this->woocommerce_wpml->products->get_original_product_language( $product_id );
|
542 |
$current_language = $this->sitepress->get_current_language();
|
543 |
|
235 |
$trnsl_labels = $this->get_attr_label_translations( $tr_product_id );
|
236 |
|
237 |
foreach ( $orig_product_attrs as $key => $orig_product_attr ) {
|
238 |
+
$sanitized_key = $this->filter_attribute_name( $orig_product_attr[ 'name' ], $original_product_id, true );
|
239 |
if( $sanitized_key != $key ) {
|
240 |
$orig_product_attrs_buff = $orig_product_attrs[ $key ];
|
241 |
unset( $orig_product_attrs[ $key ] );
|
537 |
*/
|
538 |
function filter_attribute_name( $attribute_name, $product_id, $return_sanitized = false ) {
|
539 |
|
540 |
+
if ( $product_id ) {
|
541 |
$orig_lang = $this->woocommerce_wpml->products->get_original_product_language( $product_id );
|
542 |
$current_language = $this->sitepress->get_current_language();
|
543 |
|
inc/class-wcml-emails.php
CHANGED
@@ -308,7 +308,7 @@ class WCML_Emails{
|
|
308 |
if($user){
|
309 |
$user_lang = $this->sitepress->get_user_admin_language($user->ID, true );
|
310 |
}else{
|
311 |
-
$user_lang =
|
312 |
}
|
313 |
|
314 |
$this->change_email_language( $user_lang );
|
308 |
if($user){
|
309 |
$user_lang = $this->sitepress->get_user_admin_language($user->ID, true );
|
310 |
}else{
|
311 |
+
$user_lang = $this->sitepress->get_default_language();
|
312 |
}
|
313 |
|
314 |
$this->change_email_language( $user_lang );
|
inc/class-wcml-orders.php
CHANGED
@@ -2,6 +2,9 @@
|
|
2 |
|
3 |
class WCML_Orders {
|
4 |
|
|
|
|
|
|
|
5 |
private $woocommerce_wpml;
|
6 |
private $sitepress;
|
7 |
|
@@ -305,7 +308,7 @@ class WCML_Orders {
|
|
305 |
function order_language_dropdown( $order_id ){
|
306 |
if( !get_post_meta( $order_id, '_order_currency') ) {
|
307 |
$languages = apply_filters( 'wpml_active_languages', array(), array( 'skip_missing' => 0, 'orderby' => 'code' ) );
|
308 |
-
$selected_lang = isset( $_COOKIE [
|
309 |
?>
|
310 |
<li class="wide">
|
311 |
<label><?php _e('Order language:'); ?></label>
|
@@ -351,6 +354,8 @@ class WCML_Orders {
|
|
351 |
});
|
352 |
|
353 |
");
|
|
|
|
|
354 |
}
|
355 |
}
|
356 |
|
@@ -361,11 +366,11 @@ class WCML_Orders {
|
|
361 |
die();
|
362 |
}
|
363 |
|
364 |
-
|
365 |
-
|
366 |
-
//do_action( 'wpsc_add_cookie', $cookie_name );
|
367 |
-
setcookie( $cookie_name, filter_input( INPUT_POST, 'lang', FILTER_SANITIZE_FULL_SPECIAL_CHARS ), time() + 86400, COOKIEPATH, COOKIE_DOMAIN );
|
368 |
|
|
|
|
|
369 |
}
|
370 |
|
371 |
function set_order_language_backend( $post_id, $post ){
|
2 |
|
3 |
class WCML_Orders {
|
4 |
|
5 |
+
const DASHBOARD_COOKIE_NAME = '_wcml_dashboard_order_language';
|
6 |
+
const COOKIE_TTL = 86400;
|
7 |
+
|
8 |
private $woocommerce_wpml;
|
9 |
private $sitepress;
|
10 |
|
308 |
function order_language_dropdown( $order_id ){
|
309 |
if( !get_post_meta( $order_id, '_order_currency') ) {
|
310 |
$languages = apply_filters( 'wpml_active_languages', array(), array( 'skip_missing' => 0, 'orderby' => 'code' ) );
|
311 |
+
$selected_lang = isset( $_COOKIE [ self::DASHBOARD_COOKIE_NAME ] ) ? $_COOKIE [ self::DASHBOARD_COOKIE_NAME ] : $this->sitepress->get_default_language();
|
312 |
?>
|
313 |
<li class="wide">
|
314 |
<label><?php _e('Order language:'); ?></label>
|
354 |
});
|
355 |
|
356 |
");
|
357 |
+
}else{
|
358 |
+
$this->remove_dashboard_order_language_cookie();
|
359 |
}
|
360 |
}
|
361 |
|
366 |
die();
|
367 |
}
|
368 |
|
369 |
+
setcookie( self::DASHBOARD_COOKIE_NAME, filter_input( INPUT_POST, 'lang', FILTER_SANITIZE_FULL_SPECIAL_CHARS ), time() + self::COOKIE_TTL, COOKIEPATH, COOKIE_DOMAIN );
|
370 |
+
}
|
|
|
|
|
371 |
|
372 |
+
private function remove_dashboard_order_language_cookie(){
|
373 |
+
setcookie( self::DASHBOARD_COOKIE_NAME, '', time() - self::COOKIE_TTL, COOKIEPATH, COOKIE_DOMAIN );
|
374 |
}
|
375 |
|
376 |
function set_order_language_backend( $post_id, $post ){
|
inc/class-wcml-products.php
CHANGED
@@ -37,17 +37,13 @@ class WCML_Products{
|
|
37 |
|
38 |
if ( is_admin() ) {
|
39 |
|
40 |
-
add_filter( 'woocommerce_json_search_found_products', array(
|
41 |
-
$this,
|
42 |
-
'woocommerce_json_search_found_products'
|
43 |
-
) );
|
44 |
-
|
45 |
add_filter( 'post_row_actions', array( $this, 'filter_product_actions' ), 10, 2 );
|
46 |
|
47 |
add_action( 'wp_ajax_wpml_switch_post_language', array( $this, 'switch_product_variations_language' ), 9 );
|
48 |
add_filter( 'woocommerce_product_type_query', array( $this, 'override_product_type_query' ), 10, 2 );
|
49 |
} else {
|
50 |
-
add_filter( 'woocommerce_json_search_found_products', array( $this, '
|
51 |
add_filter( 'woocommerce_related_products_args', array( $this, 'filter_related_products_args' ) );
|
52 |
add_filter( 'woocommerce_product_related_posts_query', array( $this, 'filter_related_products_query' ) );
|
53 |
add_filter( 'woocommerce_shortcode_products_query', array(
|
@@ -76,6 +72,7 @@ class WCML_Products{
|
|
76 |
|
77 |
if ( $this->sitepress->get_wp_api()->version_compare( $this->sitepress->get_wp_api()->constant( 'WC_VERSION' ), '3.6.0', '>=' ) ) {
|
78 |
add_filter( 'get_post_metadata', array( $this, 'filter_product_data' ), 10, 3 );
|
|
|
79 |
}
|
80 |
}
|
81 |
|
@@ -320,30 +317,6 @@ class WCML_Products{
|
|
320 |
return $actions;
|
321 |
}
|
322 |
|
323 |
-
/**
|
324 |
-
* Filters upsell/crosell products in the correct language.
|
325 |
-
*/
|
326 |
-
public function filter_found_products_by_language( $found_products ){
|
327 |
-
$current_page_language = $this->sitepress->get_current_language();
|
328 |
-
|
329 |
-
foreach( $found_products as $product_id => $output_v ){
|
330 |
-
$post_data = $this->wpdb->get_row(
|
331 |
-
$this->wpdb->prepare(
|
332 |
-
"SELECT * FROM {$this->wpdb->prefix}icl_translations
|
333 |
-
WHERE element_id = %d AND element_type LIKE 'post_%'", $product_id
|
334 |
-
)
|
335 |
-
);
|
336 |
-
|
337 |
-
$product_language = $post_data->language_code;
|
338 |
-
|
339 |
-
if( $product_language !== $current_page_language ){
|
340 |
-
unset( $found_products[ $product_id ] );
|
341 |
-
}
|
342 |
-
}
|
343 |
-
|
344 |
-
return $found_products;
|
345 |
-
}
|
346 |
-
|
347 |
/**
|
348 |
* Takes off translated products from the Up-sells/Cross-sells tab.
|
349 |
*/
|
@@ -365,26 +338,54 @@ class WCML_Products{
|
|
365 |
return $posts;
|
366 |
}
|
367 |
|
368 |
-
public function woocommerce_json_search_found_products( $found_products ){
|
369 |
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|| ( $parent && $this->is_original_product($parent) ) )
|
380 |
-
)
|
381 |
-
) {
|
382 |
|
383 |
-
|
384 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
385 |
}
|
386 |
|
387 |
-
return
|
388 |
}
|
389 |
|
390 |
//update menu_order fro translations after ordering original products
|
@@ -767,4 +768,16 @@ class WCML_Products{
|
|
767 |
|
768 |
return $product_type;
|
769 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
770 |
}
|
37 |
|
38 |
if ( is_admin() ) {
|
39 |
|
40 |
+
add_filter( 'woocommerce_json_search_found_products', array( $this, 'filter_wc_searched_products_on_admin' ) );
|
|
|
|
|
|
|
|
|
41 |
add_filter( 'post_row_actions', array( $this, 'filter_product_actions' ), 10, 2 );
|
42 |
|
43 |
add_action( 'wp_ajax_wpml_switch_post_language', array( $this, 'switch_product_variations_language' ), 9 );
|
44 |
add_filter( 'woocommerce_product_type_query', array( $this, 'override_product_type_query' ), 10, 2 );
|
45 |
} else {
|
46 |
+
add_filter( 'woocommerce_json_search_found_products', array( $this, 'filter_wc_searched_products_on_front' ) );
|
47 |
add_filter( 'woocommerce_related_products_args', array( $this, 'filter_related_products_args' ) );
|
48 |
add_filter( 'woocommerce_product_related_posts_query', array( $this, 'filter_related_products_query' ) );
|
49 |
add_filter( 'woocommerce_shortcode_products_query', array(
|
72 |
|
73 |
if ( $this->sitepress->get_wp_api()->version_compare( $this->sitepress->get_wp_api()->constant( 'WC_VERSION' ), '3.6.0', '>=' ) ) {
|
74 |
add_filter( 'get_post_metadata', array( $this, 'filter_product_data' ), 10, 3 );
|
75 |
+
add_filter( 'woocommerce_can_reduce_order_stock', array( $this, 'remove_post_meta_data_filter_on_checkout_stock_update' ) );
|
76 |
}
|
77 |
}
|
78 |
|
317 |
return $actions;
|
318 |
}
|
319 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
320 |
/**
|
321 |
* Takes off translated products from the Up-sells/Cross-sells tab.
|
322 |
*/
|
338 |
return $posts;
|
339 |
}
|
340 |
|
|
|
341 |
|
342 |
+
/**
|
343 |
+
* Filters products by language
|
344 |
+
*
|
345 |
+
* @param array $found_products
|
346 |
+
* @param bool $language
|
347 |
+
*
|
348 |
+
* @return array
|
349 |
+
*/
|
350 |
+
private function filter_found_products_by_language( $found_products, $language = false ){
|
|
|
|
|
|
|
351 |
|
352 |
+
if( !$language ){
|
353 |
+
$language = $this->sitepress->get_current_language();
|
354 |
+
}
|
355 |
+
|
356 |
+
foreach( $found_products as $product_id => $product_name ){
|
357 |
+
|
358 |
+
if( $this->post_translations->get_element_lang_code( $product_id ) !== $language ){
|
359 |
+
unset( $found_products[ $product_id ] );
|
360 |
+
}
|
361 |
+
}
|
362 |
+
|
363 |
+
return $found_products;
|
364 |
+
}
|
365 |
+
|
366 |
+
/**
|
367 |
+
* @param array $found_products
|
368 |
+
*
|
369 |
+
* @return array
|
370 |
+
*/
|
371 |
+
public function filter_wc_searched_products_on_front( $found_products ){
|
372 |
+
return $this->filter_found_products_by_language( $found_products );
|
373 |
+
}
|
374 |
+
|
375 |
+
/**
|
376 |
+
* @param array $found_products
|
377 |
+
*
|
378 |
+
* @return array
|
379 |
+
*/
|
380 |
+
public function filter_wc_searched_products_on_admin( $found_products ){
|
381 |
+
|
382 |
+
if ( isset( $_COOKIE['_wcml_dashboard_order_language'] ) ) {
|
383 |
+
$found_products = $this->filter_found_products_by_language( $found_products, $_COOKIE['_wcml_dashboard_order_language'] );
|
384 |
+
}else{
|
385 |
+
$found_products = $this->filter_found_products_by_language( $found_products );
|
386 |
}
|
387 |
|
388 |
+
return $found_products;
|
389 |
}
|
390 |
|
391 |
//update menu_order fro translations after ordering original products
|
768 |
|
769 |
return $product_type;
|
770 |
}
|
771 |
+
|
772 |
+
/**
|
773 |
+
* @param bool $reduce_stock
|
774 |
+
*
|
775 |
+
* @return bool
|
776 |
+
*/
|
777 |
+
public function remove_post_meta_data_filter_on_checkout_stock_update( $reduce_stock ){
|
778 |
+
if( isset( $_GET['wc-ajax'] ) && 'checkout' === $_GET['wc-ajax'] ){
|
779 |
+
remove_filter( 'get_post_metadata', array( $this, 'filter_product_data' ), 10, 3 );
|
780 |
+
}
|
781 |
+
return $reduce_stock;
|
782 |
+
}
|
783 |
}
|
inc/class-wcml-wc-shipping.php
CHANGED
@@ -98,7 +98,9 @@ class WCML_WC_Shipping{
|
|
98 |
function translate_shipping_methods_in_package( $available_methods ){
|
99 |
|
100 |
foreach($available_methods as $key => $method){
|
101 |
-
|
|
|
|
|
102 |
}
|
103 |
|
104 |
return apply_filters( 'wcml_translated_package_rates', $available_methods );
|
98 |
function translate_shipping_methods_in_package( $available_methods ){
|
99 |
|
100 |
foreach($available_methods as $key => $method){
|
101 |
+
if( apply_filters( 'wcml_translate_shipping_method_in_package', true, $key, $method ) ){
|
102 |
+
$available_methods[$key]->label = $this->translate_shipping_method_title( $method->label, $key );
|
103 |
+
}
|
104 |
}
|
105 |
|
106 |
return apply_filters( 'wcml_translated_package_rates', $available_methods );
|
inc/currencies/class-wcml-custom-prices.php
CHANGED
@@ -2,13 +2,17 @@
|
|
2 |
|
3 |
class WCML_Custom_Prices{
|
4 |
|
|
|
5 |
private $woocommerce_wpml;
|
6 |
|
7 |
-
public function __construct(
|
8 |
-
add_filter( 'init', array( $this, 'custom_prices_init' ) );
|
9 |
$this->woocommerce_wpml = $woocommerce_wpml;
|
10 |
}
|
11 |
|
|
|
|
|
|
|
|
|
12 |
public function custom_prices_init(){
|
13 |
if ( is_admin() ) {
|
14 |
add_action( 'woocommerce_variation_options', array($this, 'add_individual_variation_nonce'), 10, 3 );
|
@@ -411,50 +415,69 @@ class WCML_Custom_Prices{
|
|
411 |
}
|
412 |
}
|
413 |
|
414 |
-
|
415 |
-
|
416 |
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
|
|
421 |
|
422 |
-
|
423 |
-
foreach( $keys as $key ){
|
424 |
-
if( !isset( $custom_prices[$key] ) ){ $custom_prices[$key] = ''; }
|
425 |
-
}
|
426 |
|
427 |
-
foreach( $custom_prices as $custom_price_key => $custom_price_value ){
|
428 |
-
update_post_meta( $post_id, $custom_price_key.'_'.$code, $custom_price_value );
|
429 |
-
}
|
430 |
-
if ( $custom_prices[ '_sale_price_dates_to' ] && ! $custom_prices[ '_sale_price_dates_from' ] ) {
|
431 |
-
update_post_meta($post_id, '_sale_price_dates_from_' . $code, strtotime( 'NOW', current_time( 'timestamp' ) ) );
|
432 |
-
}
|
433 |
-
// Update price if on sale
|
434 |
-
if ( $custom_prices[ '_sale_price' ] != '' && $custom_prices[ '_sale_price_dates_to' ] == '' && $custom_prices[ '_sale_price_dates_from' ] == '' ){
|
435 |
-
$price = stripslashes( $custom_prices[ '_sale_price' ] );
|
436 |
-
update_post_meta( $post_id, '_price_'.$code, stripslashes( $custom_prices[ '_sale_price' ] ) );
|
437 |
-
}else{
|
438 |
-
$price = stripslashes( $custom_prices[ '_regular_price' ] );
|
439 |
-
update_post_meta( $post_id, '_price_'.$code, stripslashes( $custom_prices[ '_regular_price' ] ) );
|
440 |
-
}
|
441 |
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
}
|
446 |
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
|
454 |
-
|
455 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
456 |
|
457 |
-
|
458 |
|
459 |
if( isset( $_POST[ '_wcml_custom_prices' ][ $product_id ] ) ){
|
460 |
|
2 |
|
3 |
class WCML_Custom_Prices{
|
4 |
|
5 |
+
/** @var woocommerce_wpml */
|
6 |
private $woocommerce_wpml;
|
7 |
|
8 |
+
public function __construct( woocommerce_wpml $woocommerce_wpml ){
|
|
|
9 |
$this->woocommerce_wpml = $woocommerce_wpml;
|
10 |
}
|
11 |
|
12 |
+
public function add_hooks(){
|
13 |
+
add_filter( 'init', array( $this, 'custom_prices_init' ) );
|
14 |
+
}
|
15 |
+
|
16 |
public function custom_prices_init(){
|
17 |
if ( is_admin() ) {
|
18 |
add_action( 'woocommerce_variation_options', array($this, 'add_individual_variation_nonce'), 10, 3 );
|
415 |
}
|
416 |
}
|
417 |
|
418 |
+
public function update_custom_prices( $post_id, $custom_prices, $code ) {
|
419 |
+
$price = null;
|
420 |
|
421 |
+
$defaults = array(
|
422 |
+
'_sale_price_dates_to' => '',
|
423 |
+
'_sale_price_dates_from' => '',
|
424 |
+
'_sale_price' => ''
|
425 |
+
);
|
426 |
|
427 |
+
$custom_prices = array_merge( $defaults, $custom_prices );
|
|
|
|
|
|
|
428 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
429 |
|
430 |
+
foreach ( $custom_prices as $custom_price_key => $custom_price_value ) {
|
431 |
+
update_post_meta( $post_id, $custom_price_key . '_' . $code, $custom_price_value );
|
432 |
+
}
|
|
|
433 |
|
434 |
+
if ( $this->is_sale_price_valid( $custom_prices ) ){
|
435 |
+
$price = stripslashes( $custom_prices['_sale_price'] );
|
436 |
+
} else {
|
437 |
+
$price = stripslashes( $custom_prices['_regular_price'] );
|
438 |
+
$this->validate_and_update_sale_price_dates( $post_id, $code, $custom_prices );
|
439 |
+
}
|
440 |
|
441 |
+
update_post_meta( $post_id, '_price_' . $code, $price ? $price : null );
|
442 |
+
|
443 |
+
return $price;
|
444 |
+
}
|
445 |
+
|
446 |
+
/**
|
447 |
+
* @param int $post_id
|
448 |
+
* @param string $code
|
449 |
+
* @param array $custom_prices
|
450 |
+
*/
|
451 |
+
private function validate_and_update_sale_price_dates( $post_id, $code, array $custom_prices ) {
|
452 |
+
$date_from = $custom_prices['_sale_price_dates_from'];
|
453 |
+
$date_to = $custom_prices['_sale_price_dates_to'];
|
454 |
+
if ( $date_to ) {
|
455 |
+
if ( $date_to < strtotime( 'NOW', current_time( 'timestamp' ) ) ) {
|
456 |
+
update_post_meta( $post_id, '_sale_price_dates_from_' . $code, '' );
|
457 |
+
update_post_meta( $post_id, '_sale_price_dates_to_' . $code, '' );
|
458 |
+
} elseif ( ! $date_from ) {
|
459 |
+
update_post_meta( $post_id,
|
460 |
+
'_sale_price_dates_from_' . $code,
|
461 |
+
strtotime( 'NOW', current_time( 'timestamp' ) ) );
|
462 |
+
}
|
463 |
+
}
|
464 |
+
}
|
465 |
+
|
466 |
+
/**
|
467 |
+
* @param array $custom_prices
|
468 |
+
*
|
469 |
+
* @return bool
|
470 |
+
*/
|
471 |
+
protected function is_sale_price_valid( array $custom_prices ) {
|
472 |
+
$sale_price_dates_from = $custom_prices['_sale_price_dates_from'];
|
473 |
+
$sale_price_dates_to = $custom_prices['_sale_price_dates_to'];
|
474 |
+
$not_depend_on_date = $sale_price_dates_to === '' && $sale_price_dates_from === '';
|
475 |
+
$valid_sale_date = $sale_price_dates_from < strtotime( 'NOW', current_time( 'timestamp' ) );
|
476 |
+
|
477 |
+
return $custom_prices['_sale_price'] !== '' && ( $not_depend_on_date || $valid_sale_date );
|
478 |
+
}
|
479 |
|
480 |
+
public function sync_product_variations_custom_prices( $product_id ){
|
481 |
|
482 |
if( isset( $_POST[ '_wcml_custom_prices' ][ $product_id ] ) ){
|
483 |
|
inc/currencies/class-wcml-multi-currency.php
CHANGED
@@ -123,6 +123,7 @@ class WCML_Multi_Currency{
|
|
123 |
);
|
124 |
$this->admin_currency_selector->add_hooks();
|
125 |
$this->custom_prices = new WCML_Custom_Prices( $woocommerce_wpml );
|
|
|
126 |
$this->currency_switcher = new WCML_Currency_Switcher( $woocommerce_wpml, $sitepress );
|
127 |
$this->currency_switcher->add_hooks();
|
128 |
$this->currency_switcher_ajax = new WCML_Currency_Switcher_Ajax( $woocommerce_wpml );
|
123 |
);
|
124 |
$this->admin_currency_selector->add_hooks();
|
125 |
$this->custom_prices = new WCML_Custom_Prices( $woocommerce_wpml );
|
126 |
+
$this->custom_prices->add_hooks();
|
127 |
$this->currency_switcher = new WCML_Currency_Switcher( $woocommerce_wpml, $sitepress );
|
128 |
$this->currency_switcher->add_hooks();
|
129 |
$this->currency_switcher_ajax = new WCML_Currency_Switcher_Ajax( $woocommerce_wpml );
|
inc/translation-editor/class-wcml-synchronize-product-data.php
CHANGED
@@ -498,11 +498,11 @@ class WCML_Synchronize_Product_Data{
|
|
498 |
|
499 |
if ( $translations ) {
|
500 |
foreach ( $translations as $translation ) {
|
501 |
-
if ( $is_original && $product_id !== $translation ) {
|
502 |
$language_code = $this->post_translations->get_element_lang_code( $translation );
|
503 |
$this->sync_product_data( $product_id, $translation, $language_code );
|
504 |
$this->sync_date_and_parent( $product_id, $translation, $language_code );
|
505 |
-
} elseif ( $original_product_id === $translation ) {
|
506 |
$language_code = $this->post_translations->get_element_lang_code( $product_id );
|
507 |
$this->sync_product_data( $translation, $product_id, $language_code );
|
508 |
$this->sync_date_and_parent( $translation, $product_id, $language_code );
|
498 |
|
499 |
if ( $translations ) {
|
500 |
foreach ( $translations as $translation ) {
|
501 |
+
if ( $is_original && $product_id !== (int) $translation ) {
|
502 |
$language_code = $this->post_translations->get_element_lang_code( $translation );
|
503 |
$this->sync_product_data( $product_id, $translation, $language_code );
|
504 |
$this->sync_date_and_parent( $product_id, $translation, $language_code );
|
505 |
+
} elseif ( ! $is_original && $original_product_id === (int) $translation ) {
|
506 |
$language_code = $this->post_translations->get_element_lang_code( $product_id );
|
507 |
$this->sync_product_data( $translation, $product_id, $language_code );
|
508 |
$this->sync_date_and_parent( $translation, $product_id, $language_code );
|
readme.txt
CHANGED
@@ -5,7 +5,7 @@ Tags: CMS, woocommerce, commerce, ecommerce, e-commerce, products, WPML, multili
|
|
5 |
License: GPLv2
|
6 |
Requires at least: 4.7
|
7 |
Tested up to: 5.2.1
|
8 |
-
Stable tag: 4.6.
|
9 |
|
10 |
Allows running fully multilingual e-commerce sites using WooCommerce and WPML.
|
11 |
|
@@ -140,6 +140,17 @@ WooCommerce Multilingual is compatible with all major WooCommerce extensions. We
|
|
140 |
|
141 |
== Changelog ==
|
142 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
143 |
= 4.6.3 =
|
144 |
* In some cases product translation can be converted to a simple product instead of correct type after saving
|
145 |
* Fix not recalculated ratings after remove rating from admin
|
5 |
License: GPLv2
|
6 |
Requires at least: 4.7
|
7 |
Tested up to: 5.2.1
|
8 |
+
Stable tag: 4.6.5
|
9 |
|
10 |
Allows running fully multilingual e-commerce sites using WooCommerce and WPML.
|
11 |
|
140 |
|
141 |
== Changelog ==
|
142 |
|
143 |
+
= 4.6.5 =
|
144 |
+
* The Events Calendar: convert currency for event_cost.
|
145 |
+
* Wrong product price set after purchase in combination with custom prices for secondary currency and enabled stock
|
146 |
+
* Translated attributes not saving if original one contains umlauts and original product language is German or Danish
|
147 |
+
* Price not auto-calculated if you selected using custom prices and don't set a price
|
148 |
+
* After quick edit variable product variations incremented their IDs
|
149 |
+
* Added new wcml_translate_shipping_method_in_package filter
|
150 |
+
* Products not filtered by current language while search Upsells/Cross-sells on product edit screen
|
151 |
+
* Use default language if admin user not exists while sending "New Order" email to admins
|
152 |
+
* Variation description not saved on installs with 300+ variations for product
|
153 |
+
|
154 |
= 4.6.3 =
|
155 |
* In some cases product translation can be converted to a simple product instead of correct type after saving
|
156 |
* Fix not recalculated ratings after remove rating from admin
|
vendor/autoload.php
CHANGED
@@ -4,4 +4,4 @@
|
|
4 |
|
5 |
require_once __DIR__ . '/composer/autoload_real.php';
|
6 |
|
7 |
-
return
|
4 |
|
5 |
require_once __DIR__ . '/composer/autoload_real.php';
|
6 |
|
7 |
+
return ComposerAutoloaderInit2ba1fa2bed2b05e6935dfe8f0b8f9241::getLoader();
|
vendor/autoload_52.php
CHANGED
@@ -4,4 +4,4 @@
|
|
4 |
|
5 |
require_once dirname(__FILE__) . '/composer'.'/autoload_real_52.php';
|
6 |
|
7 |
-
return
|
4 |
|
5 |
require_once dirname(__FILE__) . '/composer'.'/autoload_real_52.php';
|
6 |
|
7 |
+
return ComposerAutoloaderInit5b128786b2c78c76b4e062ebf198a7b3::getLoader();
|
vendor/composer/autoload_real.php
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
// autoload_real.php @generated by Composer
|
4 |
|
5 |
-
class
|
6 |
{
|
7 |
private static $loader;
|
8 |
|
@@ -19,15 +19,15 @@ class ComposerAutoloaderInit6de590272da4e9672c17db908f09e178
|
|
19 |
return self::$loader;
|
20 |
}
|
21 |
|
22 |
-
spl_autoload_register(array('
|
23 |
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
24 |
-
spl_autoload_unregister(array('
|
25 |
|
26 |
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
|
27 |
if ($useStaticLoader) {
|
28 |
require_once __DIR__ . '/autoload_static.php';
|
29 |
|
30 |
-
call_user_func(\Composer\Autoload\
|
31 |
} else {
|
32 |
$map = require __DIR__ . '/autoload_namespaces.php';
|
33 |
foreach ($map as $namespace => $path) {
|
@@ -48,19 +48,19 @@ class ComposerAutoloaderInit6de590272da4e9672c17db908f09e178
|
|
48 |
$loader->register(true);
|
49 |
|
50 |
if ($useStaticLoader) {
|
51 |
-
$includeFiles = Composer\Autoload\
|
52 |
} else {
|
53 |
$includeFiles = require __DIR__ . '/autoload_files.php';
|
54 |
}
|
55 |
foreach ($includeFiles as $fileIdentifier => $file) {
|
56 |
-
|
57 |
}
|
58 |
|
59 |
return $loader;
|
60 |
}
|
61 |
}
|
62 |
|
63 |
-
function
|
64 |
{
|
65 |
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
66 |
require $file;
|
2 |
|
3 |
// autoload_real.php @generated by Composer
|
4 |
|
5 |
+
class ComposerAutoloaderInit2ba1fa2bed2b05e6935dfe8f0b8f9241
|
6 |
{
|
7 |
private static $loader;
|
8 |
|
19 |
return self::$loader;
|
20 |
}
|
21 |
|
22 |
+
spl_autoload_register(array('ComposerAutoloaderInit2ba1fa2bed2b05e6935dfe8f0b8f9241', 'loadClassLoader'), true, true);
|
23 |
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
24 |
+
spl_autoload_unregister(array('ComposerAutoloaderInit2ba1fa2bed2b05e6935dfe8f0b8f9241', 'loadClassLoader'));
|
25 |
|
26 |
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
|
27 |
if ($useStaticLoader) {
|
28 |
require_once __DIR__ . '/autoload_static.php';
|
29 |
|
30 |
+
call_user_func(\Composer\Autoload\ComposerStaticInit2ba1fa2bed2b05e6935dfe8f0b8f9241::getInitializer($loader));
|
31 |
} else {
|
32 |
$map = require __DIR__ . '/autoload_namespaces.php';
|
33 |
foreach ($map as $namespace => $path) {
|
48 |
$loader->register(true);
|
49 |
|
50 |
if ($useStaticLoader) {
|
51 |
+
$includeFiles = Composer\Autoload\ComposerStaticInit2ba1fa2bed2b05e6935dfe8f0b8f9241::$files;
|
52 |
} else {
|
53 |
$includeFiles = require __DIR__ . '/autoload_files.php';
|
54 |
}
|
55 |
foreach ($includeFiles as $fileIdentifier => $file) {
|
56 |
+
composerRequire2ba1fa2bed2b05e6935dfe8f0b8f9241($fileIdentifier, $file);
|
57 |
}
|
58 |
|
59 |
return $loader;
|
60 |
}
|
61 |
}
|
62 |
|
63 |
+
function composerRequire2ba1fa2bed2b05e6935dfe8f0b8f9241($fileIdentifier, $file)
|
64 |
{
|
65 |
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
66 |
require $file;
|
vendor/composer/autoload_real_52.php
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
// autoload_real_52.php generated by xrstf/composer-php52
|
4 |
|
5 |
-
class
|
6 |
private static $loader;
|
7 |
|
8 |
public static function loadClassLoader($class) {
|
@@ -19,9 +19,9 @@ class ComposerAutoloaderInitbbd0c134ac587a0753eb6f856bac0721 {
|
|
19 |
return self::$loader;
|
20 |
}
|
21 |
|
22 |
-
spl_autoload_register(array('
|
23 |
self::$loader = $loader = new xrstf_Composer52_ClassLoader();
|
24 |
-
spl_autoload_unregister(array('
|
25 |
|
26 |
$vendorDir = dirname(dirname(__FILE__));
|
27 |
$baseDir = dirname($vendorDir);
|
2 |
|
3 |
// autoload_real_52.php generated by xrstf/composer-php52
|
4 |
|
5 |
+
class ComposerAutoloaderInit5b128786b2c78c76b4e062ebf198a7b3 {
|
6 |
private static $loader;
|
7 |
|
8 |
public static function loadClassLoader($class) {
|
19 |
return self::$loader;
|
20 |
}
|
21 |
|
22 |
+
spl_autoload_register(array('ComposerAutoloaderInit5b128786b2c78c76b4e062ebf198a7b3', 'loadClassLoader'), true /*, true */);
|
23 |
self::$loader = $loader = new xrstf_Composer52_ClassLoader();
|
24 |
+
spl_autoload_unregister(array('ComposerAutoloaderInit5b128786b2c78c76b4e062ebf198a7b3', '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
|
8 |
{
|
9 |
public static $files = array (
|
10 |
'b45b351e6b6f7487d819961fef2fda77' => __DIR__ . '/..' . '/jakeasmith/http_build_url/src/http_build_url.php',
|
@@ -242,10 +242,10 @@ class ComposerStaticInit6de590272da4e9672c17db908f09e178
|
|
242 |
public static function getInitializer(ClassLoader $loader)
|
243 |
{
|
244 |
return \Closure::bind(function () use ($loader) {
|
245 |
-
$loader->prefixLengthsPsr4 =
|
246 |
-
$loader->prefixDirsPsr4 =
|
247 |
-
$loader->prefixesPsr0 =
|
248 |
-
$loader->classMap =
|
249 |
|
250 |
}, null, ClassLoader::class);
|
251 |
}
|
4 |
|
5 |
namespace Composer\Autoload;
|
6 |
|
7 |
+
class ComposerStaticInit2ba1fa2bed2b05e6935dfe8f0b8f9241
|
8 |
{
|
9 |
public static $files = array (
|
10 |
'b45b351e6b6f7487d819961fef2fda77' => __DIR__ . '/..' . '/jakeasmith/http_build_url/src/http_build_url.php',
|
242 |
public static function getInitializer(ClassLoader $loader)
|
243 |
{
|
244 |
return \Closure::bind(function () use ($loader) {
|
245 |
+
$loader->prefixLengthsPsr4 = ComposerStaticInit2ba1fa2bed2b05e6935dfe8f0b8f9241::$prefixLengthsPsr4;
|
246 |
+
$loader->prefixDirsPsr4 = ComposerStaticInit2ba1fa2bed2b05e6935dfe8f0b8f9241::$prefixDirsPsr4;
|
247 |
+
$loader->prefixesPsr0 = ComposerStaticInit2ba1fa2bed2b05e6935dfe8f0b8f9241::$prefixesPsr0;
|
248 |
+
$loader->classMap = ComposerStaticInit2ba1fa2bed2b05e6935dfe8f0b8f9241::$classMap;
|
249 |
|
250 |
}, null, ClassLoader::class);
|
251 |
}
|
wpml-woocommerce.php
CHANGED
@@ -8,7 +8,7 @@
|
|
8 |
Text Domain: woocommerce-multilingual
|
9 |
Requires at least: 4.7
|
10 |
Tested up to: 5.2.1
|
11 |
-
Version: 4.6.
|
12 |
WC requires at least: 3.3.0
|
13 |
WC tested up to: 3.6.3
|
14 |
*/
|
@@ -17,7 +17,7 @@ if ( defined( 'WCML_VERSION' ) ) {
|
|
17 |
return;
|
18 |
}
|
19 |
|
20 |
-
define( 'WCML_VERSION', '4.6.
|
21 |
define( 'WCML_PLUGIN_PATH', dirname( __FILE__ ) );
|
22 |
define( 'WCML_PLUGIN_FOLDER', basename( WCML_PLUGIN_PATH ) );
|
23 |
define( 'WCML_LOCALE_PATH', WCML_PLUGIN_PATH . '/locale' );
|
8 |
Text Domain: woocommerce-multilingual
|
9 |
Requires at least: 4.7
|
10 |
Tested up to: 5.2.1
|
11 |
+
Version: 4.6.5
|
12 |
WC requires at least: 3.3.0
|
13 |
WC tested up to: 3.6.3
|
14 |
*/
|
17 |
return;
|
18 |
}
|
19 |
|
20 |
+
define( 'WCML_VERSION', '4.6.5' );
|
21 |
define( 'WCML_PLUGIN_PATH', dirname( __FILE__ ) );
|
22 |
define( 'WCML_PLUGIN_FOLDER', basename( WCML_PLUGIN_PATH ) );
|
23 |
define( 'WCML_LOCALE_PATH', WCML_PLUGIN_PATH . '/locale' );
|