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 / class-wcml-orders.php
woocommerce-multilingual / inc Last commit date
admin-menus 1 week ago currencies 1 week ago template-classes 1 week ago translation-editor 1 week ago class-wcml-ajax-setup.php 1 week ago class-wcml-attributes.php 1 week ago class-wcml-capabilities.php 1 week ago class-wcml-cart-removed-items-widget.php 1 year ago class-wcml-cart-switch-lang-functions.php 1 week ago class-wcml-cart-sync-warnings.php 1 week ago class-wcml-cart.php 1 week ago class-wcml-comments.php 1 week ago class-wcml-compatibility.php 1 week ago class-wcml-coupons.php 1 week ago class-wcml-dependencies.php 1 week ago class-wcml-emails.php 1 week ago class-wcml-endpoints.php 1 week ago class-wcml-install.php 1 week ago class-wcml-languages-upgrader.php 1 week ago class-wcml-locale.php 1 week ago class-wcml-orders.php 1 week ago class-wcml-products-screen-options.php 1 week ago class-wcml-products.php 1 week ago class-wcml-reports.php 1 week ago class-wcml-requests.php 1 week ago class-wcml-resources.php 1 week ago class-wcml-store-pages.php 1 week ago class-wcml-terms.php 1 week ago class-wcml-tp-support.php 1 week ago class-wcml-troubleshooting.php 1 week ago class-wcml-upgrade.php 1 week ago class-wcml-url-translation.php 1 week ago class-wcml-wc-gateways.php 1 week ago class-wcml-wc-shipping.php 1 week ago class-wcml-wc-strings.php 1 week ago class-wcml-widgets.php 1 week ago constants.php 1 week ago functions-pure.php 1 week ago functions.php 1 week ago installer-loader.php 1 week ago missing-php-functions.php 1 week ago wcml-core-functions.php 1 week ago wcml-switch-lang-request.php 1 week ago
class-wcml-orders.php
331 lines
1 <?php
2
3 use WCML\Orders\Helper as OrdersHelper;
4 use WPML\FP\Fns;
5 use WPML\FP\Maybe;
6 use WPML\FP\Obj;
7 use WCML\Utilities\WCTaxonomies;
8 use function WPML\FP\curryN;
9 use function WPML\FP\invoke;
10
11 class WCML_Orders {
12
13 const DASHBOARD_COOKIE_NAME = '_wcml_dashboard_order_language';
14 const COOKIE_TTL = 86400;
15 const KEY_LANGUAGE = 'wpml_language';
16
17 private $woocommerce_wpml;
18
19 private $sitepress;
20
21 public function __construct( $woocommerce_wpml, $sitepress ) {
22 $this->woocommerce_wpml = $woocommerce_wpml;
23 $this->sitepress = $sitepress;
24
25 add_action( 'init', [ $this, 'init' ] );
26
27 add_action( 'wp_ajax_woocommerce_checkout', [ $this, 'switch_to_current' ], 9 );
28 add_action( 'wp_ajax_nopriv_woocommerce_checkout', [ $this, 'switch_to_current' ], 9 );
29
30 add_action( 'wp_ajax_wcml_order_delete_items', [ $this, 'order_delete_items' ] );
31 }
32
33 public function init() {
34 add_action( 'woocommerce_checkout_update_order_meta', [ $this, 'set_order_language' ] );
35 add_action( 'woocommerce_before_order_object_save', [ $this, 'setOrderLanguageBeforeSave' ] );
36
37 add_filter( 'icl_lang_sel_copy_parameters', [ $this, 'append_query_parameters' ] );
38
39 add_filter( 'the_comments', [ $this, 'get_filtered_comments' ], 10, 2 );
40
41 add_action( 'woocommerce_process_shop_order_meta', [ $this, 'set_order_language_backend' ] );
42 add_action(
43 'woocommerce_order_actions_start',
44 [ $this, 'order_language_dropdown' ],
45 11
46 );
47
48 add_action( 'woocommerce_before_order_itemmeta', [ $this, 'backend_before_order_itemmeta' ], 100, 3 );
49 add_action( 'woocommerce_after_order_itemmeta', [ $this, 'backend_after_order_itemmeta' ], 100, 3 );
50
51 add_filter( 'woocommerce_get_item_downloads', [ $this, 'filter_downloadable_product_items' ], 10, 3 );
52 add_filter(
53 'woocommerce_customer_get_downloadable_products',
54 [ $this, 'filter_customer_get_downloadable_products' ],
55 10
56 );
57
58 if ( is_admin() ) {
59 $this->maybe_set_dashboard_cookie();
60 }
61 }
62
63 public function get_filtered_comments( $comments, $commentQuery ) {
64 if ( 'order_note' !== Obj::path( [ 'query_vars', 'type' ], $commentQuery ) ) {
65 return $comments;
66 }
67
68 $ifIdentifiedUser = function () {
69 return (bool) get_current_user_id();
70 };
71
72 $translateInWoocommerce = \WPML\FP\partialRight( 'translate', 'woocommerce' );
73
74 $translateComment = Obj::over( Obj::lensProp( 'comment_content' ), $translateInWoocommerce );
75
76 return Maybe::of( $comments )
77 ->filter( $ifIdentifiedUser )
78 ->map( Fns::map( $translateComment ) )
79 ->getOrElse( $comments );
80 }
81
82 public function backend_before_order_itemmeta( $item_id, $item, $product ) {
83 global $sitepress;
84
85 if ( $this->get_order_language_by_item_id( $item_id ) != $sitepress->get_user_admin_language( get_current_user_id(), true ) ) {
86 foreach ( $item['item_meta'] as $key => $item_meta ) {
87 if ( taxonomy_exists( wc_attribute_taxonomy_name( $key ) ) || WCTaxonomies::isProductAttribute( $key ) ) {
88 $item_meta = (array) $item_meta;
89 foreach ( $item_meta as $value ) {
90 $this->force_update_itemmeta( $item_id, $key, $value, $sitepress->get_user_admin_language( get_current_user_id(), true ) );
91 }
92 }
93 }
94 }
95 }
96
97 public function backend_after_order_itemmeta( $item_id, $item, $product ) {
98 global $sitepress;
99
100 $order_languge = $this->get_order_language_by_item_id( $item_id );
101 if ( $order_languge != $sitepress->get_user_admin_language( get_current_user_id(), true ) ) {
102 foreach ( $item['item_meta'] as $key => $item_meta ) {
103 if ( taxonomy_exists( wc_attribute_taxonomy_name( $key ) ) || WCTaxonomies::isProductAttribute( $key ) ) {
104 $item_meta = (array) $item_meta;
105 foreach ( $item_meta as $value ) {
106 $this->force_update_itemmeta( $item_id, $key, $value, $order_languge );
107 }
108 }
109 }
110 }
111 }
112
113 public function get_order_language_by_item_id( $item_id ) {
114 global $wpdb;
115
116 $order_id = $wpdb->get_var( $wpdb->prepare( "SELECT order_id FROM {$wpdb->prefix}woocommerce_order_items WHERE order_item_id = %d", $item_id ) );
117
118 return self::getLanguage( $order_id );
119 }
120
121 public function force_update_itemmeta( $item_id, $key, $value, $languge ) {
122 global $wpdb, $woocommerce_wpml;
123
124 $taxonomy = ! WCTaxonomies::isProductAttribute( $key ) ? wc_attribute_taxonomy_name( $key ) : $key;
125 $term_id = $woocommerce_wpml->terms->wcml_get_term_id_by_slug( $taxonomy, $value );
126 $translated_term = $woocommerce_wpml->terms->wcml_get_translated_term( $term_id, $taxonomy, $languge );
127
128 if ( $translated_term ) {
129 $value = $translated_term->slug;
130 $wpdb->update(
131 $wpdb->prefix . 'woocommerce_order_itemmeta',
132 [ 'meta_value' => $value ],
133 [
134 'order_item_id' => $item_id,
135 'meta_key' => $key,
136 ]
137 );
138 }
139 }
140
141 public function set_order_language( $order_id ) {
142 if ( ! self::getLanguage( $order_id ) ) {
143 self::setLanguage( $order_id, ICL_LANGUAGE_CODE );
144 }
145 }
146
147 public function setOrderLanguageBeforeSave( $order ) {
148 if (
149 ! in_array( $order->get_status(), [ 'checkout-draft', 'auto-draft' ], true )
150 && ! $order->get_meta( self::KEY_LANGUAGE )
151 ) {
152 $order->add_meta_data( self::KEY_LANGUAGE, $this->sitepress->get_current_language(), true );
153 wp_cache_delete( $order->generate_meta_cache_key( $order->get_id(), 'orders' ), 'orders' );
154 }
155 }
156
157 public function append_query_parameters( $parameters ) {
158
159 if ( is_order_received_page() || is_checkout() ) {
160 if ( ! in_array( 'order', $parameters ) ) {
161 $parameters[] = 'order';
162 }
163 if ( ! in_array( 'key', $parameters ) ) {
164 $parameters[] = 'key';
165 }
166 }
167
168 return $parameters;
169 }
170
171 public function switch_to_current() {
172 $this->woocommerce_wpml->emails->change_email_language( $this->sitepress->get_current_language() );
173 }
174
175 public function order_language_dropdown( $order_id ) {
176 if ( ! OrdersHelper::getCurrency( $order_id ) ) {
177 $languages = apply_filters(
178 'wpml_active_languages',
179 [],
180 [
181 'skip_missing' => 0,
182 'orderby' => 'code',
183 ]
184 );
185 $selected_lang = $_COOKIE [ self::DASHBOARD_COOKIE_NAME ] ?? $this->sitepress->get_default_language();
186 ?>
187 <li class="wide">
188 <label><?php _e( 'Order language:' ); ?></label>
189 <select id="dropdown_shop_order_language" name="wcml_shop_order_language">
190 <?php if ( ! empty( $languages ) ) : ?>
191
192 <?php foreach ( $languages as $l ) : ?>
193
194 <option
195 value="<?php echo esc_attr( $l['language_code'] ); ?>" <?php echo $selected_lang == $l['language_code'] ? 'selected="selected"' : ''; ?>><?php echo esc_html( $l['translated_name'] ); ?></option>
196
197 <?php endforeach; ?>
198
199 <?php endif; ?>
200 </select>
201 </li>
202 <?php
203 $wcml_set_dashboard_order_language_nonce = esc_js( wp_create_nonce( 'set_dashboard_order_language' ) );
204 $wcml_set_dashboard_order_language_message = esc_js( __( 'All the products will be removed from the current order in order to change the language', 'woocommerce-multilingual' ) );
205 $wcml_set_dashboard_order_language_script = <<<JS
206 var order_lang_current_value = jQuery('#dropdown_shop_order_language option:selected').val();
207
208 jQuery('#dropdown_shop_order_language').on('change', function(){
209 if(confirm('$wcml_set_dashboard_order_language_message')){
210 var lang = jQuery(this).val();
211
212 jQuery.ajax({
213 url: ajaxurl,
214 type: 'post',
215 dataType: 'json',
216 data: {action: 'wcml_order_delete_items', order_id: woocommerce_admin_meta_boxes.post_id, lang: lang , wcml_nonce: '$wcml_set_dashboard_order_language_nonce' },
217 success: function( response ){
218 if(typeof response.error !== 'undefined'){
219 alert(response.error);
220 }else{
221 window.location = window.location.href;
222 }
223 }
224 });
225 }else{
226 jQuery(this).val( order_lang_current_value );
227 return false;
228 }
229 });
230 JS;
231
232 $handle = 'wcml_set_dashboard_order_language_dropdown';
233 wp_register_script( $handle, '', [ 'jquery' ], WCML_VERSION, true );
234 wp_enqueue_script( $handle );
235 wp_add_inline_script( $handle, $wcml_set_dashboard_order_language_script );
236 } else {
237 $this->remove_dashboard_order_language_cookie();
238 }
239 }
240
241 public function order_delete_items() {
242 $nonce = filter_input( INPUT_POST, 'wcml_nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
243 if ( ! $nonce || ! wp_verify_nonce( $nonce, 'set_dashboard_order_language' ) ) {
244 echo json_encode( [ 'error' => __( 'Invalid nonce', 'woocommerce-multilingual' ) ] );
245 die();
246 }
247
248 $this->set_dashboard_order_language_cookie( filter_input( INPUT_POST, 'lang', FILTER_SANITIZE_FULL_SPECIAL_CHARS ) );
249 }
250
251 private function set_dashboard_order_language_cookie( $language ) {
252 setcookie( self::DASHBOARD_COOKIE_NAME, $language, time() + self::COOKIE_TTL, COOKIEPATH, COOKIE_DOMAIN );
253 }
254
255 private function remove_dashboard_order_language_cookie() {
256 setcookie( self::DASHBOARD_COOKIE_NAME, '', time() - self::COOKIE_TTL, COOKIEPATH, COOKIE_DOMAIN );
257 }
258
259 private function maybe_set_dashboard_cookie() {
260 if ( ! isset( $_COOKIE [ self::DASHBOARD_COOKIE_NAME ] ) && OrdersHelper::isOrderCreateAdminScreen() ) {
261 $this->set_dashboard_order_language_cookie( $this->sitepress->get_default_language() );
262 }
263 }
264
265 public function set_order_language_backend( $orderId ) {
266 if ( isset( $_POST['wcml_shop_order_language'] ) ) {
267 self::setLanguage( $orderId, filter_input( INPUT_POST, 'wcml_shop_order_language', FILTER_SANITIZE_FULL_SPECIAL_CHARS ) );
268 }
269 }
270
271 public function filter_downloadable_product_items( $files, $item, $object ) {
272 if ( ! $object ) {
273 return $files;
274 }
275
276 $order_language = self::getLanguage( $object->get_id() );
277
278 if ( $item->get_variation_id() > 0 ) {
279 $translated_variation_id = apply_filters( 'wpml_object_id', $item->get_variation_id(), 'product_variation', false, $order_language );
280 if ( ! is_null( $translated_variation_id ) ) {
281 $item->set_variation_id( $translated_variation_id );
282 }
283 } else {
284 $translated_product_id = apply_filters( 'wpml_object_id', $item->get_product_id(), 'product', false, $order_language );
285 if ( ! is_null( $translated_product_id ) ) {
286 $item->set_product_id( $translated_product_id );
287 }
288 }
289
290 remove_filter( 'woocommerce_get_item_downloads', [ $this, 'filter_downloadable_product_items' ], 10 );
291
292 $files = $item->get_item_downloads();
293
294 add_filter( 'woocommerce_get_item_downloads', [ $this, 'filter_downloadable_product_items' ], 10, 3 );
295
296 return $files;
297 }
298
299 public function filter_customer_get_downloadable_products( $downloads ) {
300
301 foreach ( $downloads as $key => $download ) {
302
303 $translated_id = apply_filters( 'wpml_object_id', $download['product_id'], get_post_type( $download['product_id'] ), false, $this->sitepress->get_current_language() );
304
305 if ( $translated_id ) {
306 $downloads[ $key ]['product_name'] = get_the_title( $translated_id );
307 }
308 }
309
310 return $downloads;
311 }
312
313 public static function getLanguage( $orderId = null ) {
314 $getLanguage = function( $orderId ) {
315 $orderId = apply_filters( 'wcml_order_id_for_language', $orderId );
316
317 return Maybe::fromNullable( \wc_get_order( $orderId ) )
318 ->map( invoke( 'get_meta' )->with( self::KEY_LANGUAGE ) )
319 ->getOrElse( false );
320 };
321
322 return call_user_func_array( curryN( 1, $getLanguage ), func_get_args() );
323 }
324
325 public static function setLanguage( $orderId, $language ) {
326 Maybe::fromNullable( \wc_get_order( $orderId ) )
327 ->map( Fns::tap( invoke( 'update_meta_data' )->with( self::KEY_LANGUAGE, $language ) ) )
328 ->map( invoke( 'save' ) );
329 }
330 }
331