multi_currency = $multi_currency; $this->woocommerce_wpml = $woocommerce_wpml; $this->wp = $wp; if ( is_admin() ) { add_filter( 'init', [ $this, 'orders_init' ] ); } } public function orders_init() { add_action( 'restrict_manage_posts', [ $this, 'show_orders_currencies_selector' ] ); $this->wp->add_query_var( '_order_currency' ); add_filter( 'posts_join', [ $this, 'filter_orders_by_currency_join' ] ); add_filter( 'posts_where', [ $this, 'filter_orders_by_currency_where' ] ); // override current currency value when viewing order in admin. add_filter( 'woocommerce_currency_symbol', [ $this, '_use_order_currency_symbol' ] ); // new order currency/language switchers. add_action( 'woocommerce_process_shop_order_meta', [ $this, 'set_order_currency_on_update' ], 10, 2 ); add_action( 'woocommerce_order_actions_start', [ $this, 'show_order_currency_selector' ] ); add_filter( 'woocommerce_order_get_items', [ $this, 'set_totals_for_order_items' ], 10, 2 ); add_filter( 'woocommerce_hidden_order_itemmeta', [ $this, 'add_woocommerce_hidden_order_itemmeta' ] ); add_action( 'wp_ajax_wcml_order_set_currency', [ $this, 'set_order_currency_on_ajax_update' ] ); // dashboard status screen. if ( current_user_can( 'view_woocommerce_reports' ) || current_user_can( 'manage_woocommerce' ) || current_user_can( 'publish_shop_orders' ) ) { // filter query to get order by status. add_filter( 'query', [ $this, 'filter_order_status_query' ] ); } add_action( 'woocommerce_email_before_order_table', [ $this, 'fix_currency_before_order_email' ] ); add_action( 'woocommerce_email_after_order_table', [ $this, 'fix_currency_after_order_email' ] ); if ( is_admin() ) { add_filter( 'woocommerce_order_get_currency', [ $this, 'get_currency_for_new_order' ], 10, 2 ); } } public function show_orders_currencies_selector() { global $wp_query, $typenow; if ( 'shop_order' !== $typenow ) { return; } $currency_codes = $this->multi_currency->get_currency_codes(); $currencies = get_woocommerce_currencies(); ?> query['_order_currency'] ) ) { $join .= " JOIN {$wpdb->postmeta} wcml_pm ON {$wpdb->posts}.ID = wcml_pm.post_id AND wcml_pm.meta_key='_order_currency'"; } return $join; } public function filter_orders_by_currency_where( $where ) { global $wp_query, $typenow; if ( $typenow == 'shop_order' && ! empty( $wp_query->query['_order_currency'] ) ) { $where .= " AND wcml_pm.meta_value = '" . esc_sql( $wp_query->query['_order_currency'] ) . "'"; } return $where; } public function _use_order_currency_symbol( $currency ) { if ( ! function_exists( 'get_current_screen' ) ) { return $currency; } $current_screen = get_current_screen(); remove_filter( 'woocommerce_currency_symbol', [ $this, '_use_order_currency_symbol' ] ); if ( ! empty( $current_screen ) && $current_screen->id == 'shop_order' ) { $the_order = new WC_Order( get_the_ID() ); if ( $the_order ) { $order_currency = $the_order->get_currency(); if ( ! $order_currency && isset( $_COOKIE['_wcml_order_currency'] ) ) { $order_currency = $_COOKIE['_wcml_order_currency']; } $currency = get_woocommerce_currency_symbol( $order_currency ); } } elseif ( ( isset( $_POST['action'] ) && in_array( $_POST['action'], [ 'woocommerce_add_order_item', 'woocommerce_remove_order_item', 'woocommerce_calc_line_taxes', 'woocommerce_save_order_items', ] ) ) || ( isset( $_GET['action'] ) && $_GET['action'] == 'woocommerce_json_search_products_and_variations' ) ) { if ( isset( $_COOKIE['_wcml_order_currency'] ) ) { $currency = get_woocommerce_currency_symbol( $_COOKIE['_wcml_order_currency'] ); } elseif ( isset( $_POST['order_id'] ) && $order_currency = get_post_meta( sanitize_text_field( $_POST['order_id'] ), '_order_currency', true ) ) { $currency = get_woocommerce_currency_symbol( $order_currency ); } if ( isset( $_SERVER['HTTP_REFERER'] ) ) { $arg = parse_url( $_SERVER['HTTP_REFERER'] ); if ( isset( $arg['query'] ) ) { parse_str( $arg['query'], $arg ); if ( isset( $arg['post'] ) && get_post_type( $arg['post'] ) == 'shop_order' ) { $currency = get_woocommerce_currency_symbol( get_post_meta( $arg['post'], '_order_currency', true ) ); } } } } add_filter( 'woocommerce_currency_symbol', [ $this, '_use_order_currency_symbol' ] ); return $currency; } public function set_order_currency_on_update( $post_id, $post ) { if ( isset( $_POST['wcml_shop_order_currency'] ) ) { update_post_meta( $post_id, '_order_currency', filter_input( INPUT_POST, 'wcml_shop_order_currency', FILTER_SANITIZE_FULL_SPECIAL_CHARS ) ); } } public function show_order_currency_selector( $order_id ) { if ( ! get_post_meta( $order_id, '_order_currency' ) ) { $current_order_currency = $this->get_order_currency_cookie(); $wc_currencies = get_woocommerce_currencies(); $currencies = $this->multi_currency->get_currency_codes(); ?>
  • set_converted_totals_for_item( $item, $this->get_order_coupons_objects( $order ) ); } } return $items; } /** * @param WC_Order $order * * @return array */ private function get_order_coupons_objects( $order ) { remove_filter( 'woocommerce_order_get_items', [ $this, 'set_totals_for_order_items' ], 10 ); $order_coupons = $order->get_items( 'coupon' ); $coupons_objects = []; if ( $order_coupons ) { foreach ( $order_coupons as $coupon ) { $coupon_data = $coupon->get_data(); $coupons_objects[] = new WC_Coupon( $coupon_data['code'] ); } } add_filter( 'woocommerce_order_get_items', [ $this, 'set_totals_for_order_items' ], 10, 2 ); return $coupons_objects; } public function add_woocommerce_hidden_order_itemmeta( $itemmeta ) { $itemmeta[] = $this->get_converted_meta_key( 'subtotal' ); $itemmeta[] = $this->get_converted_meta_key( 'total' ); $itemmeta[] = '_wcml_total_qty'; return $itemmeta; } /** * @param WC_Order_Item_Product $item * @param array $coupons * @param int|bool $order_id * @param string|bool $order_currency */ public function set_converted_totals_for_item( $item, $coupons, $order_id = false, $order_currency = false ) { if ( 'line_item' === $item->get_type() ) { if ( ! $order_currency ) { $order_id = $order_id ?: intval( $_POST['order_id'] ); $order_currency = get_post_meta( $order_id, '_order_currency', true ); if ( ! $order_currency ) { $order_currency = $this->get_order_currency_cookie(); if ( in_array( $_POST['action'], [ 'woocommerce_add_order_item', 'woocommerce_save_order_items', ], true ) ) { update_post_meta( $order_id, '_order_currency', $order_currency ); } } } if ( ! isset( $this->multi_currency->prices ) ) { $this->multi_currency->prices = new WCML_Multi_Currency_Prices( $this->multi_currency, $this->woocommerce_wpml->get_setting( 'currency_options' ) ); $this->multi_currency->prices->add_hooks(); } $product_id = $item->get_variation_id() ? $item->get_variation_id() : $item->get_product_id(); $original_product_id = $this->woocommerce_wpml->products->get_original_product_id( $product_id ); $converted_price = get_post_meta( $original_product_id, '_price_' . $order_currency, true ); $converted_totals = [ 'total' => 0, 'subtotal' => 0, ]; foreach ( array_keys( $converted_totals ) as $key ) { if ( 'total' === $key && $item->get_total() !== $item->get_subtotal() ) { $converted_totals[ $key ] = $item->get_total(); } else { if ( ! $converted_price ) { $converted_meta_key = $this->get_converted_meta_key( $key ); if ( ! $item->meta_exists( $converted_meta_key ) || ( $item->meta_exists( '_wcml_total_qty' ) && $item->get_quantity() !== (int) $item->get_meta( '_wcml_total_qty' ) ) ) { $item_price = $this->multi_currency->prices->raw_price_filter( $item->get_product()->get_price(), $order_currency ); $converted_totals[ $key ] = $this->get_converted_item_meta( $key, $item_price, false, $item, $order_currency, $coupons ); $item->update_meta_data( $converted_meta_key, $converted_totals[ $key ] ); } else { if ( 'total' === $key ) { $converted_totals[ $key ] = $item->get_meta( $converted_meta_key ); } else { $converted_totals[ $key ] = $this->get_item_meta( $item, $key ); } } } else { $converted_totals[ $key ] = $this->get_converted_item_meta( $key, $converted_price, true, $item, $order_currency, $coupons ); } } call_user_func_array( [ $item, 'set_' . $key ], [ $converted_totals[ $key ] ] ); } $item->update_meta_data( '_wcml_total_qty', $item->get_quantity() ); $item->save(); } } /** * @param string $key * * @return string */ private function get_converted_meta_key( $key ) { return self::WCML_CONVERTED_META_KEY_PREFIX . $key; } /** * @param WC_Order_Item_Product $item * @param string $key * * @return bool */ private function is_value_changed( $item, $key ) { $converted_meta_key = $this->get_converted_meta_key( $key ); if ( ! $item->meta_exists( $converted_meta_key ) ) { return true; } $get_key = 'get_' . $key; return $item->$get_key() !== $item->get_meta( $converted_meta_key ); } /** * @param WC_Order_Item_Product $item * @param string $key * * @return mixed */ private function get_item_meta( $item, $key ) { $converted_meta_key = $this->get_converted_meta_key( $key ); if ( $this->is_value_changed( $item, $key ) ) { $get_key = 'get_' . $key; return $item->$get_key(); } else { return $item->get_meta( $converted_meta_key ); } } /** * @param string $meta * @param string $item_price * @param bool $is_custom_price * @param WC_Order_Item_Product $item * @param string $order_currency * @param array $coupons * * @return int */ private function get_converted_item_meta( $meta, $item_price, $is_custom_price, $item, $order_currency, $coupons ) { if ( 'total' === $meta && $coupons ) { $discount_amount = 0; foreach ( $coupons as $coupon ) { if ( $coupon->is_type( 'percent' ) ) { $discount_amount += $coupon->get_discount_amount( $item_price ); } elseif ( $coupon->is_type( 'fixed_product' ) ) { $coupon_discount = $coupon->get_discount_amount( $item_price, [], true ); if ( $is_custom_price && $coupon_discount != $item_price ) { $coupon_discount = $this->multi_currency->prices->raw_price_filter( $coupon_discount, $order_currency ); } $discount_amount += $coupon_discount; } } $item_price = $item_price - $discount_amount; } $converted_meta = $item->get_quantity() * wc_get_price_excluding_tax( $item->get_product(), [ 'price' => $item_price ] ); return $converted_meta; } public function get_order_currency_cookie() { if ( isset( $_COOKIE['_wcml_order_currency'] ) ) { return $_COOKIE['_wcml_order_currency']; } else { return wcml_get_woocommerce_currency_option(); } } public function set_order_currency_on_ajax_update() { $nonce = filter_input( INPUT_POST, 'wcml_nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS ); if ( ! $nonce || ! wp_verify_nonce( $nonce, 'set_order_currency' ) ) { echo json_encode( [ 'error' => __( 'Invalid nonce', 'woocommerce-multilingual' ) ] ); die(); } $currency = filter_input( INPUT_POST, 'currency', FILTER_SANITIZE_FULL_SPECIAL_CHARS ); $cookie_name = '_wcml_order_currency'; // @todo uncomment or delete when #wpmlcore-5796 is resolved. // do_action( 'wpsc_add_cookie', $cookie_name ); setcookie( $cookie_name, $currency, time() + 86400, COOKIEPATH, COOKIE_DOMAIN ); $return['currency'] = $currency; echo json_encode( $return ); die(); } /* * Filter status query * * @param string $query * * @return string * */ public function filter_order_status_query( $query ) { global $pagenow, $wpdb; if ( $pagenow == 'index.php' ) { $sql = "SELECT post_status, COUNT( * ) AS num_posts FROM {$wpdb->posts} WHERE post_type = 'shop_order' GROUP BY post_status"; if ( $query == $sql ) { $currency = $this->multi_currency->admin_currency_selector->get_cookie_dashboard_currency(); $query = "SELECT post_status, COUNT( * ) AS num_posts FROM {$wpdb->posts} WHERE post_type = 'shop_order' AND ID IN ( SELECT order_currency.post_id FROM {$wpdb->postmeta} AS order_currency WHERE order_currency.meta_key = '_order_currency' AND order_currency.meta_value = '{$currency}' ) GROUP BY post_status"; } } return $query; } // handle currency in order emails before handled in woocommerce. public function fix_currency_before_order_email( $order ) { $order_currency = $order->get_currency(); if ( ! $order_currency ) { return; } $this->order_currency = $order_currency; add_filter( 'woocommerce_currency', [ $this, '_override_woocommerce_order_currency_temporarily' ] ); } public function fix_currency_after_order_email( $order ) { unset( $this->order_currency ); remove_filter( 'woocommerce_currency', [ $this, '_override_woocommerce_order_currency_temporarily' ] ); } public function _override_woocommerce_order_currency_temporarily( $currency ) { if ( isset( $this->order_currency ) ) { $currency = $this->order_currency; } return $currency; } public function get_currency_for_new_order( $value, $order ) { if ( did_action( 'current_screen' ) ) { $current_screen = get_current_screen(); if ( ! empty( $current_screen ) && $current_screen->id == 'shop_order' ) { $order_id = method_exists( $order, 'get_id' ) ? $order->get_id() : $order->id; $order_currency = get_post_meta( $order_id, '_order_currency', true ); if ( empty( $order_currency ) ) { $value = $this->get_order_currency_cookie(); } } } return $value; } }