PluginProbe ʕ •ᴥ•ʔ
WPML Multilingual & Multicurrency for WooCommerce / 5.5.7
WPML Multilingual & Multicurrency for WooCommerce v5.5.7
5.5.7 5.3.8 5.3.9 5.4.3 5.4.4 5.4.5 5.5.1 5.5.1.1 5.5.2.2 5.5.2.3 5.5.3 5.5.3.1 5.5.4 5.5.5 5.5.6 trunk 0.9 1.0 1.1 1.2 1.3 1.4 1.5 2.0 2.2 2.3 2.3.1 2.3.2 3.0 3.0.1 3.1 3.2 3.2.1 3.2.2 3.3 3.3.1 3.3.2 3.3.3 3.3.4 3.4 3.4.1 3.4.2 3.4.3 3.5 3.5.1 3.5.2 3.5.3 3.5.4 3.5.5 3.6 3.6.1 3.6.10 3.6.11 3.6.2 3.6.3 3.6.4 3.6.5 3.6.5.1 3.6.6 3.6.7 3.6.8 3.6.9 3.7 3.7.1 3.7.10 3.7.11 3.7.12 3.7.13 3.7.14 3.7.15 3.7.16 3.7.2 3.7.3 3.7.4 3.7.5 3.7.6 3.7.7 3.7.8 3.7.9 3.8.0 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.8.6 3.9.0 3.9.1 3.9.1.1 3.9.2 3.9.3 3.9.4 3.9.5 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4 4.10.0 4.10.1 4.10.2 4.10.3 4.10.4 4.11.2 4.11.3.2 4.11.5 4.11.6 4.12.1 4.12.4 4.12.5 4.12.6 4.2.0 4.2.0.1 4.2.1 4.2.1.1 4.2.10 4.2.2 4.2.3 4.2.4 4.2.5 4.2.6 4.2.7 4.2.7.1 4.2.8 4.2.8.1 4.2.9 4.3.0 4.3.1 4.3.2 4.3.2.1 4.3.3 4.3.4 4.3.5 4.3.6 4.3.7 4.4.0 4.4.1 4.4.2 4.4.2.1 4.5.0 4.6.0 4.6.1 4.6.2 4.6.2.1 4.6.3 4.6.5 4.6.6 4.6.7 4.7.0 4.7.1 4.7.2 4.7.3 4.7.4 4.7.5 4.7.6 4.7.7 4.7.8 4.7.9 4.8.0 4.9.0 4.9.1 5.0.1 5.0.2 5.1.1 5.1.2 5.1.3 5.2.0 5.2.1 5.3.2 5.3.3.1 5.3.4 5.3.5 5.3.6 5.3.7
woocommerce-multilingual / inc / currencies / class-wcml-multi-currency-orders.php
woocommerce-multilingual / inc / currencies Last commit date
currency-switcher 4 weeks ago class-wcml-custom-prices.php 4 weeks ago class-wcml-multi-currency-configuration.php 4 weeks ago class-wcml-multi-currency-coupons.php 1 year ago class-wcml-multi-currency-install.php 4 weeks ago class-wcml-multi-currency-orders.php 4 weeks ago class-wcml-multi-currency-prices.php 4 weeks ago class-wcml-multi-currency-reports.php 4 weeks ago class-wcml-multi-currency-resources.php 4 weeks ago class-wcml-multi-currency-shipping.php 4 weeks ago class-wcml-multi-currency-table-rate-shipping.php 4 weeks ago class-wcml-multi-currency.php 4 weeks ago class-wcml-price-filter.php 4 weeks ago class-wcml-w3tc-multi-currency.php 4 weeks ago
class-wcml-multi-currency-orders.php
433 lines
1 <?php
2
3 use WCML\COT\Helper as COTHelper;
4 use WCML\Orders\Legacy\Helper as LegacyHelper;
5 use WCML\Orders\Helper as OrdersHelper;
6 use WPML\FP\Obj;
7
8 class WCML_Multi_Currency_Orders {
9 const WCML_CONVERTED_META_KEY_PREFIX = '_wcml_converted_';
10
11 private $multi_currency;
12 private $woocommerce_wpml;
13 private $wp;
14
15 private $order_currency;
16
17 public function __construct( WCML_Multi_Currency $multi_currency, woocommerce_wpml $woocommerce_wpml, WP $wp ) {
18 $this->multi_currency = $multi_currency;
19 $this->woocommerce_wpml = $woocommerce_wpml;
20 $this->wp = $wp;
21
22 if ( is_admin() ) {
23 add_filter( 'init', [ $this, 'orders_init' ] );
24 }
25 }
26
27 public function orders_init() {
28
29 add_action( 'restrict_manage_posts', [ $this, 'show_orders_currencies_selector' ] );
30 add_action( 'woocommerce_order_list_table_restrict_manage_orders', [ $this, 'show_orders_currencies_selector' ] );
31 $this->wp->add_query_var( '_order_currency' );
32
33 add_filter( 'woocommerce_order_list_table_prepare_items_query_args', [ $this, 'hpos_filter_orders_by_currency' ] );
34 add_filter( 'posts_join', [ $this, 'filter_orders_by_currency_join' ] );
35 add_filter( 'posts_where', [ $this, 'filter_orders_by_currency_where' ] );
36
37 add_action( 'woocommerce_process_shop_order_meta', [ $this, 'set_order_currency_on_update' ] );
38 add_action( 'woocommerce_order_actions_start', [ $this, 'show_order_currency_selector' ] );
39
40 add_filter( 'woocommerce_ajax_order_item', [ $this, 'setTotalsForOrderNewItem' ], 10, 3 );
41 add_action( 'woocommerce_before_save_order_item', [ $this, 'updateTotalsForOrderItem' ] );
42
43 add_filter( 'woocommerce_hidden_order_itemmeta', [ $this, 'add_woocommerce_hidden_order_itemmeta' ] );
44
45 add_action( 'wp_ajax_wcml_order_set_currency', [ $this, 'set_order_currency_on_ajax_update' ] );
46
47 if ( current_user_can( 'view_woocommerce_reports' ) || current_user_can( 'manage_woocommerce' ) || current_user_can( 'publish_shop_orders' ) ) {
48 add_filter( 'query', [ $this, 'filter_order_status_query' ] );
49 }
50
51 add_action( 'woocommerce_email_before_order_table', [ $this, 'fix_currency_before_order_email' ] );
52 add_action( 'woocommerce_email_after_order_table', [ $this, 'fix_currency_after_order_email' ] );
53
54 if ( is_admin() ) {
55 add_filter( 'woocommerce_order_get_currency', [ $this, 'get_currency_for_new_order' ], 10, 2 );
56 }
57 }
58
59 public function show_orders_currencies_selector() {
60 global $wp_query;
61
62 if ( ! OrdersHelper::isOrderListAdminScreen() ) {
63 return;
64 }
65
66 $currency_codes = $this->multi_currency->get_currency_codes();
67 $currencies = get_woocommerce_currencies();
68 ?>
69 <select id="dropdown_shop_order_currency" name="_order_currency">
70 <option value=""><?php esc_html_e( 'Show all currencies', 'woocommerce-multilingual' ); ?></option>
71 <?php
72 foreach ( $currency_codes as $currency ) {
73 $selected = '';
74 if ( isset( $wp_query->query['_order_currency'] ) ) {
75 $selected = selected( $currency, $wp_query->query['_order_currency'], false );
76 } elseif ( COTHelper::isOrderListAdminScreen() ) {
77 $selected = selected( $currency, $this->get_order_currency_get(), false );
78 }
79 $text = sprintf( '%s (%s)', $currencies[ $currency ], get_woocommerce_currency_symbol( $currency ) );
80 ?>
81 <option value="<?php echo esc_html( $currency ); ?>" <?php echo wp_kses_post( $selected ); ?>><?php echo esc_html( $text ); ?></option>
82 <?php
83 }
84 ?>
85 </select>
86 <?php
87 }
88
89 private function is_currency_filter_applied() {
90 global $wp_query;
91 return ! empty( $wp_query->query['_order_currency'] );
92 }
93
94 public function filter_orders_by_currency_join( $join ) {
95 global $wpdb;
96
97 if ( LegacyHelper::isOrderListAdminScreen() && $this->is_currency_filter_applied() ) {
98 $join .= " JOIN {$wpdb->postmeta} wcml_pm ON {$wpdb->posts}.ID = wcml_pm.post_id AND wcml_pm.meta_key='_order_currency'";
99 }
100
101 return $join;
102 }
103
104 public function filter_orders_by_currency_where( $where ) {
105 global $wp_query;
106
107 if ( LegacyHelper::isOrderListAdminScreen() && $this->is_currency_filter_applied() ) {
108 $where .= " AND wcml_pm.meta_value = '" . esc_sql( $wp_query->query['_order_currency'] ) . "'";
109 }
110
111 return $where;
112 }
113
114 public function hpos_filter_orders_by_currency( $query_args ) {
115 $currencyFromAdminSelector = $this->get_order_currency_get();
116
117 if ( $currencyFromAdminSelector ) {
118 $query_args['currency'] = $currencyFromAdminSelector;
119 }
120
121 return $query_args;
122 }
123
124 public function set_order_currency_on_update( $post_id ) {
125
126 if ( isset( $_POST['wcml_shop_order_currency'] ) ) {
127 OrdersHelper::setCurrency( $post_id, filter_input( INPUT_POST, 'wcml_shop_order_currency', FILTER_SANITIZE_FULL_SPECIAL_CHARS ) );
128 }
129
130 }
131
132 public function show_order_currency_selector( $order_id ) {
133 $order = wc_get_order( $order_id );
134
135 if ( $order && $order->get_status() === 'auto-draft' ) {
136
137 $current_order_currency = $this->get_order_currency_cookie();
138
139 $wc_currencies = get_woocommerce_currencies();
140 $currencies = $this->multi_currency->get_currency_codes();
141
142 ?>
143 <li class="wide">
144 <label><?php _e( 'Order currency:', 'woocommerce-multilingual' ); ?></label>
145 <select id="dropdown_shop_order_currency" name="wcml_shop_order_currency">
146
147 <?php foreach ( $currencies as $currency ) : ?>
148
149 <option value="<?php echo esc_attr( $currency ); ?>" <?php echo $current_order_currency == $currency ? 'selected="selected"' : ''; ?>><?php echo $wc_currencies[ $currency ]; ?></option>
150
151 <?php endforeach; ?>
152
153 </select>
154 </li>
155 <?php
156 $wcml_set_order_currency_nonce = esc_js( wp_create_nonce( 'set_order_currency' ) );
157 $wcml_set_order_currency_message = esc_js( __( 'All the products will be removed from the current order in order to change the currency', 'woocommerce-multilingual' ) );
158 $wcml_set_order_currency_script = <<<JS
159 var order_currency_current_value = jQuery('#dropdown_shop_order_currency option:selected').val();
160
161 jQuery('#dropdown_shop_order_currency').on('change', function(){
162
163 if(confirm('$wcml_set_order_currency_message')){
164 jQuery.ajax({
165 url: ajaxurl,
166 type: 'post',
167 dataType: 'json',
168 data: {
169 action: 'wcml_order_set_currency',
170 currency: jQuery('#dropdown_shop_order_currency option:selected').val(),
171 wcml_nonce: '$wcml_set_order_currency_nonce'
172 },
173 success: function( response ){
174 if(typeof response.error !== 'undefined'){
175 alert(response.error);
176 }else{
177 window.location = window.location.href;
178 }
179 }
180 });
181 }else{
182 jQuery(this).val( order_currency_current_value );
183 return false;
184 }
185
186 });
187
188 JS;
189
190 $handle = 'wcml_show_order_currency_dropdown';
191 wp_register_script( $handle, '', [ 'jquery' ], WCML_VERSION, true );
192 wp_enqueue_script( $handle );
193 wp_add_inline_script( $handle, $wcml_set_order_currency_script );
194
195 }
196
197 }
198
199 public function setTotalsForOrderNewItem( $item, $itemId, $order ) {
200 if ( false === $item ) {
201 return $item;
202 }
203
204 if ( 'line_item' !== $item->get_type() ) {
205 return $item;
206 }
207
208 $orderCurrency = $this->setCurrencyFromOrder( $order->get_id() );
209 $convertedPrice = $this->getConvertedItemPrice( $item, $orderCurrency );
210 $orderCoupons = $this->get_order_coupons_objects( $order );
211
212 $propertiesToConvert = [ 'total', 'subtotal' ];
213
214 foreach ( $propertiesToConvert as $propertySlug ) {
215 $convertedMetaKey = $this->get_converted_meta_key( $propertySlug );
216 $convertedValue = $this->get_converted_item_meta( $propertySlug, $convertedPrice, false, $item, $orderCurrency, $orderCoupons );
217 $item->update_meta_data( $convertedMetaKey, $convertedValue );
218 call_user_func_array( [ $item, 'set_' . $propertySlug ], [ $convertedValue ] );
219 }
220
221 $item->update_meta_data( '_wcml_total_qty', $item->get_quantity() );
222 $item->save();
223
224 $order->add_item( $item );
225
226 return $item;
227 }
228
229 private function setCurrencyFromOrder( $orderId ) {
230 $orderCurrency = OrdersHelper::getCurrency( $orderId );
231
232 if ( ! $orderCurrency ) {
233 $orderCurrency = $this->get_order_currency_cookie();
234 OrdersHelper::setCurrency( $orderId, $orderCurrency );
235 }
236
237 return $orderCurrency;
238 }
239
240 private function getConvertedItemPrice( $item, $orderCurrency ) {
241 $productId = $item->get_variation_id() ? $item->get_variation_id() : $item->get_product_id();
242 $originalProductId = $this->woocommerce_wpml->products->get_original_product_id( $productId );
243
244 $convertedPrice = get_post_meta( $originalProductId, '_price_' . $orderCurrency, true );
245 if ( ! $convertedPrice ) {
246 $convertedPrice = $this->multi_currency->prices->raw_price_filter( $item->get_product()->get_price(), $orderCurrency );
247 }
248
249 return $convertedPrice;
250 }
251
252 public function updateTotalsForOrderItem( $item ) {
253 if ( 'line_item' !== $item->get_type() ) {
254 return;
255 }
256
257 $propertiesToUpdate = [ 'total', 'subtotal' ];
258
259 foreach ( $propertiesToUpdate as $propertySlug ) {
260 $converted_meta_key = $this->get_converted_meta_key( $propertySlug );
261 if ( $this->is_value_changed( $item, $propertySlug ) ) {
262 $get_key = 'get_' . $propertySlug;
263 $item->update_meta_data( $converted_meta_key, $item->$get_key() );
264 }
265 }
266
267 $item->update_meta_data( '_wcml_total_qty', $item->get_quantity() );
268 }
269
270 private function get_order_coupons_objects( $order ) {
271 $order_coupons = $order->get_items( 'coupon' );
272 $coupons_objects = [];
273
274 if ( $order_coupons ) {
275 foreach ( $order_coupons as $coupon ) {
276 $coupon_data = $coupon->get_data();
277 $coupons_objects[] = new WC_Coupon( $coupon_data['code'] );
278 }
279 }
280
281 return $coupons_objects;
282 }
283
284 public function add_woocommerce_hidden_order_itemmeta( $itemmeta ) {
285 $itemmeta[] = $this->get_converted_meta_key( 'subtotal' );
286 $itemmeta[] = $this->get_converted_meta_key( 'total' );
287 $itemmeta[] = '_wcml_total_qty';
288
289 return $itemmeta;
290 }
291
292 public function set_converted_totals_for_item( $item, $coupons, $order_id = false, $order_currency = false ) {
293 }
294
295 private function get_converted_meta_key( $key ) {
296 return self::WCML_CONVERTED_META_KEY_PREFIX . $key;
297 }
298
299 private function is_value_changed( $item, $key ) {
300 $converted_meta_key = $this->get_converted_meta_key( $key );
301
302 if ( ! $item->meta_exists( $converted_meta_key ) ) {
303 return true;
304 }
305
306 $get_key = 'get_' . $key;
307 $foo = $item->$get_key();
308 $bar = $item->get_meta( $converted_meta_key );
309
310 return $item->$get_key() !== $item->get_meta( $converted_meta_key );
311 }
312
313 private function get_converted_item_meta( $meta, $item_price, $is_custom_price, $item, $order_currency, $coupons ) {
314
315 if ( 'total' === $meta && $coupons ) {
316
317 $discount_amount = 0;
318 foreach ( $coupons as $coupon ) {
319 if ( $coupon->is_type( 'percent' ) ) {
320 $discount_amount += $coupon->get_discount_amount( $item_price );
321 } elseif ( $coupon->is_type( 'fixed_product' ) ) {
322 $coupon_discount = $coupon->get_discount_amount( $item_price, [], true );
323
324 if ( $is_custom_price && $coupon_discount != $item_price ) {
325 $coupon_discount = $this->multi_currency->prices->raw_price_filter( $coupon_discount, $order_currency );
326 }
327 $discount_amount += $coupon_discount;
328 }
329 }
330 $item_price = $item_price - $discount_amount;
331 }
332
333 return $item->get_quantity() * wc_get_price_excluding_tax( $item->get_product(), [ 'price' => $item_price ] );
334 }
335
336 public function get_order_currency_cookie() {
337
338 if ( isset( $_COOKIE['_wcml_order_currency'] ) ) {
339 return $_COOKIE['_wcml_order_currency'];
340 }
341 return wcml_get_woocommerce_currency_option();
342 }
343
344
345 private function get_order_currency_get() {
346 return isset( $_GET['_order_currency'] ) ? sanitize_text_field( wp_unslash( $_GET['_order_currency'] ) ) : null;
347 }
348
349 public function set_order_currency_on_ajax_update() {
350 $nonce = filter_input( INPUT_POST, 'wcml_nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
351 if ( ! $nonce || ! wp_verify_nonce( $nonce, 'set_order_currency' ) ) {
352 echo json_encode( [ 'error' => __( 'Invalid nonce', 'woocommerce-multilingual' ) ] );
353 die();
354 }
355 $currency = filter_input( INPUT_POST, 'currency', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
356
357 $cookie_name = '_wcml_order_currency';
358 setcookie( $cookie_name, $currency, time() + 86400, COOKIEPATH, COOKIE_DOMAIN );
359
360 $return['currency'] = $currency;
361
362 echo json_encode( $return );
363
364 die();
365 }
366
367 public function filter_order_status_query( $query ) {
368 global $pagenow, $wpdb;
369
370 if ( $pagenow == 'index.php' ) {
371 $sql = "SELECT post_status, COUNT( * ) AS num_posts FROM {$wpdb->posts} WHERE post_type = 'shop_order' GROUP BY post_status";
372
373 if ( $query == $sql ) {
374
375 $currency = $this->multi_currency->admin_currency_selector->get_cookie_dashboard_currency();
376
377 if ( COTHelper::isUsageEnabled() ) {
378 $query = $wpdb->prepare( "SELECT `status` as `post_status`, COUNT( * ) AS `num_posts` FROM " . COTHelper::getTableName() . "
379 WHERE `type` = 'shop_order' AND `currency` = %s GROUP BY status"
380 , $currency );
381 } else {
382 $query = $wpdb->prepare ("SELECT post_status, COUNT( * ) AS num_posts FROM {$wpdb->posts}
383 WHERE post_type = 'shop_order' AND ID IN
384 ( SELECT order_currency.post_id FROM {$wpdb->postmeta} AS order_currency
385 WHERE order_currency.meta_key = '_order_currency'
386 AND order_currency.meta_value = %s )
387 GROUP BY post_status"
388 , $currency );
389 }
390
391 }
392 }
393
394 return $query;
395 }
396
397 public function fix_currency_before_order_email( $order ) {
398
399 $order_currency = $order->get_currency();
400
401 if ( ! $order_currency ) {
402 return;
403 }
404
405 $this->order_currency = $order_currency;
406 add_filter( 'woocommerce_currency', [ $this, '_override_woocommerce_order_currency_temporarily' ] );
407 }
408
409 public function fix_currency_after_order_email( $order ) {
410 unset( $this->order_currency );
411 remove_filter( 'woocommerce_currency', [ $this, '_override_woocommerce_order_currency_temporarily' ] );
412 }
413
414 public function _override_woocommerce_order_currency_temporarily( $currency ) {
415 if ( isset( $this->order_currency ) ) {
416 $currency = $this->order_currency;
417 }
418
419 return $currency;
420 }
421
422 public function get_currency_for_new_order( $currency, $order ) {
423 if ( OrdersHelper::isOrderCreateAdminScreen() || OrdersHelper::isEditingNewOrderItems() ) {
424 $orderId = method_exists( $order, 'get_id' ) ? $order->get_id() : Obj::prop( 'id', $order );
425 $orderCurrency = OrdersHelper::getCurrency( $orderId, true );
426
427 return $orderCurrency ?: $this->get_order_currency_cookie();
428 }
429
430 return $currency;
431 }
432 }
433